zoukankan      html  css  js  c++  java
  • 认识一下ES6的Reflect和Proxy

    Reflect

    Reflect要替代Object的很多方法, 将Object对象一些明显属于言内部的方法放到了Reflect对象上,有13个方法

    Reflect.apply(target, thisArg, args)
    Reflect.construct(target, args)
    Reflect.get(target, name, receiver)
    Reflect.set(target, name, value, receiver)
    Reflect.defineProperty(target, name, desc)
    Reflect.deleteProperty(target, name)
    Reflect.has(target, name)
    Reflect.ownKeys(target)
    Reflect.isExtensible(target)
    Reflect.preventExtensions(target)
    Reflect.getOwnPropertyDescriptor(target, name)
    Reflect.getPrototypeOf(target)
    Reflect.setPrototypeOf(target, prototype)
    

     Reflect所有方法的第一个参数都必须是对象,不能是简单数据类型,比如1,true; 

    Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数.
    Function.prototype.apply.call <===> Reflect.apply

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

    Proxy

    Proxy代理可以对对象(不可以为一个简单数据类型比如1, true, 'string'设置proxy.)的某一些行为进行接截,利用这一点,可以对外界的访问进行过滤和改写。

    Proxy的构造方法,需要传递两个参数,第一个参数是要进行过滤拦截的对象,第二参数也是一个对象,这个对象指明对哪些行为进行接截

    const obj ={
      name:'',age:'18',
      get showName() {return `${this.name}年龄${this.age}`}  
    }
    
    const proxyOpr = {
     get: function(target, key, receiver){
         console.log(`getting ${key}`);
          return Reflect.get(target, key, receiver);
     },
      set: function(target, key, value, receiver){
        console.log(`setting ${key} as '${value}'`);
         return Reflect.set(target, key, value, receiver); 
      } 
    }
    
    const proxy = new Proxy(obj, proxyOpr);
    proxy.name='test proxy';
    console.log(proxy.showName);
    

    // setting name as 'test proxy'

    // getting showName
    // getting name
    // getting age
    // test proxy年龄18

    对obj的取值及赋值操作都被拦截并添加了一个日志打印。

    注意点:

    1 get和apply过滤都存在时,会走get过滤。

    2 生成的代理对象会取得this.

    3 可以用Proxy.revocable来取消代理

    let target = {};
    let handler = {};
    
    let {proxy, revoke} = Proxy.revocable(target, handler);
    
    proxy.foo = 123;
    proxy.foo // 123
    
    revoke(); //取消代理
    proxy.foo //TypeError: Revoked

     new Proxy()产生的对象的数据类型是和目标对象一值的,即目标对象是funtion,它的proxy也为function

    const proxy1 = new Proxy(function(i, j){return i+j;},
    {
      apply: function(target, thisBinding, args){
        console.log(args);
        return Reflect.apply(target, thisBinding, args); //切记写return 
      }
    })
    const t = proxy1(1, 2);
    console.log(t);
    typeof proxy1
    // [1,2]
    // 3
    // "function"
    

     Proxy实例也可以作为其他对象的原型对象

    var proxy = new Proxy({}, {
      get: function(target, property) {
        return 35;
      }
    });
    
    var obj ={name:'tt'};
    Reflect.setPrototypeOf(obj,proxy)
    
    obj.name // tt
    obj.age //35
    

      obj对象本身没有age属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截.而obj自身具有属性,读取时不会被拦截。

     

    代理的出现可以让目标对象只关注于自己的行为,与外界的沟通都可以放到proxy里来完成。比如说猫叫老鼠跑。其实猫可以不知道有没有老鼠或是别的动物,它只实现自己的叫就可以了。到底是谁跑可以交给猫的代理来完成。代理里拦截到猫叫,就可以加入猫食物链下所有动物都跑的行为。

    Reflect和Proxy里可以拦截的方法是一一对应的。只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。

    冥冥中觉得js的代理跟spring里的代理有些类似,可以学习对比一下。

  • 相关阅读:
    nginx+vue+thinkphp5.1部署,解决前端刷新404,以及前端404解决后,后台又404的问题
    centos7.4挂载硬盘
    thinkphp5.1+layui2.x 时间戳转换为日期格式
    解决linux(ubuntu18)下无法挂载ntfs磁盘,并读写挂载硬盘
    sublime中nodejs配置
    jquery 中的$("obj").html('')中的html动态改变之后点击事件失效
    js怎么弹出变量的数据类型
    异步操作执行后子页面重新修改父页面iframe高度
    iframe标签父页面高度自适应
    string.Format()方法、Graphics类、DrawImage方法
  • 原文地址:https://www.cnblogs.com/Gift/p/10826089.html
Copyright © 2011-2022 走看看