zoukankan      html  css  js  c++  java
  • ES6 (7):Reflect

    Reflect 配合proxy  使对象的操作更加函数化。

    大部分Reflect 的全局方法或者说静态方法与proxy一致。

    相比Object  返回值更合理:修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false

    如果 Proxy对象和 Reflect对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了receiver,那么Reflect.set会触发Proxy.defineProperty拦截。

    let p = {
      a: 'a'
    };
    
    let handler = {
      set(target, key, value, receiver) {
        console.log('set');
        Reflect.set(target, key, value, receiver)
      },
      defineProperty(target, key, attribute) {
        console.log('defineProperty');
        Reflect.defineProperty(target, key, attribute);
      }
    };
    
    let obj = new Proxy(p, handler);
    obj.a = 'A';
    // set
    // defineProperty
    

     因为Proxy.setreceiver参数总是指向当前的 Proxy实例(即上例的obj),而Reflect.set一旦传入receiver,就会将属性赋值到receiver上面(即obj),导致触发defineProperty拦截。如果Reflect.set没有传入receiver,那么就不会触发defineProperty拦截。

    Reflect.construct: 等同于new  target(args) 创建实例对象。

    function Greeting(name) {
      this.name = name;
    }
    
    // new 的写法
    const instance = new Greeting('张三');
    
    // Reflect.construct 的写法
    const instance = Reflect.construct(Greeting, ['张三']);
    

     如果Reflect.construct()方法的第一个参数不是函数会报错

    Reflect.getPrototypeOf:用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj)

    const myObj = new FancyThing();
    
    // 旧写法
    Object.getPrototypeOf(myObj) === FancyThing.prototype;
    
    // 新写法
    Reflect.getPrototypeOf(myObj) === FancyThing.prototype;
    

     Reflect.getPrototypeOfObject.getPrototypeOf的一个区别是,如果参数不是对象,Object.getPrototypeOf会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf会报错

    Reflect.apply(): 如果要绑定一个函数的this对象,可以这样写fn.apply(obj, args),但是如果函数定义了自己的apply方法,就只能写成Function.prototype.apply.call(fn, obj, args),采用Reflect对象可以简化这种操作。

    Reflect.defineProperty:为对象定义属性

    const p = new Proxy({}, {
      defineProperty(target, prop, descriptor) {
        console.log(descriptor);
        return Reflect.defineProperty(target, prop, descriptor);
      }
    });
    
    p.foo = 'bar';
    // {value: "bar", writable: true, enumerable: true, configurable: true}
    
    p.foo // "bar"
    

     Proxy.defineProperty对属性赋值设置了拦截,然后使用Reflect.defineProperty完成了赋值

    Reflect.preventExtensions:用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。

    观察者模式:使用 Proxy 写一个观察者模式的最简单实现,即实现observableobserve这两个函数。思路observable函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数

    const queuedObservers = new Set();
    
    const observe = fn => queuedObservers.add(fn);
    const observable = obj => new Proxy(obj, {set});
    
    function set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      queuedObservers.forEach(observer => observer());
      return result;
    }
    

     首先:需要定义observable ,定义代理(添加需要被代理的对象),在执行set(例子中为set 对象的add 添加)操作时,代理对象首先在目标对象(原始对象)设置属性与值,然后循环执行观察者函数(例子中print方法)。

    const person = observable({
      name: '张三',
      age: 20
    });
    
    function print() {
      console.log(`${person.name}, ${person.age}`)
    }
    
    observe(print);
    person.name = '李四';
    // 输出
    // 李四, 20
    
    成灰之前,抓紧时间做点事!!
  • 相关阅读:
    VM网络故障问题
    Weblogic无法创建域报段错误排查过程记录
    xmind8 Pro序列号
    vs2015下载地址(安装包丢失或损坏)
    复旦大学数学学院20级高等代数I期中考试大题的高等代数II解法及其推广
    复旦高等代数I(21级)每周一题
    Nginx alias root 和 try_files 基本使用
    Nginx location 和 proxy_pass路径配置详解
    (PMP)第7版
    scheduler源码分析——preempt抢占
  • 原文地址:https://www.cnblogs.com/jony-it/p/10967729.html
Copyright © 2011-2022 走看看