ES6中的Proxy和Reflect对象的方法详解

首先看一个例子:

 var outerT=function(){return 'I am qinliang'}
        var handler={
        	apply:function(target,ctx,args){
        		//第一个参数为目标对象
        		return 'ctx='+ctx.name+",args="+args+",target="+(target===outerT);
        	}
        }
        var p=new Proxy(outerT,handler);
         console.log(p.apply({name:'qinliang'},[1,2,3]));
打印结果为ctx=qinliang,args=1,2,3,target=true,因此target就是目标对象,ctx就是为目标对象传递的上下文,args就是为目标对象传递的额外参数。这个例子所有的拦截都在代理中被处理了,如何把代理中的处理结果传入到最终的对象上继续调用,见下面的例子:

  var outerT=function(left,right){
        	console.log(this);
        	return left+right;
        }
        var handler={
        	apply:function(target,ctx,args){
        		//第一个参数为目标对象,这里通过Reflect.apply把上次处理的结果传递给被代理执行
        		return Reflect.apply(...arguments)*2;
        	}
        }
        var p=new Proxy(outerT,handler);
         console.log(p.apply({name:'qinliang'},[2,3]));
         //通过apply传入了上下文
         console.log(p(2,3));
         //直接调用也会被拦截,上下文为window
         console.log(Reflect.apply(p,null,[2,3]));
         //通过Reflect.apply也会被调用,上下文为window

注意:Reflect.apply(fn, obj, args)相当于Function.prototype.apply.call(fn, obj, args),其中obj就是上下文的,而args就是传入的参数!

has函数用于隐藏某些属性从而不被in操作符发现,而enumerate用于拦截for..in操作符:

    var obj={a:10};
       Object.preventExtensions(obj);
       var p=new Proxy(obj,{
       	 has:function(target,prop){
       	 	return false;
       	 }
       })
        console.log(a in p);
        //如果原对象不可配置或者禁止扩展,这时候has会报错
constructor用于拦截new操作符,如果返回值不是对象会抛出错误

  var p=new Proxy(function(){},{
        	construct:function(target,argumentsList){
        		//这里不是数组,即使你new p(1,2);时候传入了多个对象
        		console.log(argumentsList.join(','));
        		return {value:argumentsList[0]*10}
        	}
        })
       new p(1,2);
isExtensible方法拦截Object.isExtensible操作

   var p=new Proxy({},{
         	isExtensible:function(target){
         		//拦截Object.isExtensible方法
         		return false;
         	}
         })
         Object.isExtensible(p);
注意:这个方法有一个限制,Object.isExtensible(proxy)===Object.isExtensible(target),如果不满足这个条件就会抛出错误!这里就会报错
preventExtensions用于拦截Object.preventExtensions方法:

      var p=new Proxy({},{
      	preventExtensions:function(target){
      		console.log('called');
      		Object.preventExtensions(target);
      		//这里必须手动调用让target无法扩展,后面的 Object.preventExtensions(p);才能调用
      		return true;
      	}
      })
      Object.preventExtensions(p);
Proxy.revocable方法

     let target={};
        let handler={};
        let {proxy,revoke}=Proxy.revocable(target,handler);
        proxy.foo=123;
        console.log(proxy.foo);
        //打印123
        revoke();
        console.log(proxy.foo);
        //报错
这个方法返回一个对象,其中proxy就是产生的Proxy实例,而revoke是一个函数,可以取消Proxy实例
   Reflect和Proxy对象一样,也是ES6为了操作对象而提供的新的API:
     (1)将Object对象一些明显属于语言层面的方法放在Reflect对象上,现阶段某些方法同时存在于Object和Reflect对象上,未来只会部署在Reflect对象上
     (2)修改了某些Object方法返回值让他变得更加合理。如Object.defineProperty在无法定义属性时候抛出错误,但是Reflect.defineProperty返回false
     (3)Object操作都变成函数行为。某些Object操作是命令式的,如name in obj和delete obj[name],而Reflect.has,Reflect.deletePropery变成函数行为

     (4)Reflect方法和Proxy方法一一对应,只要是Proxy对象上存在那么就能在Reflect中找到,于是Proxy对象可以方便的调用对应的Reflect方法完成默认行为,作为修改行为的基础。也就是说,不管Proxy如何修改默认行为,你总是可以在Reflect上获取默认行为

我们看看Proxy和Reflect中最重要的一个参数receiver的用法:

         var obj={
         	get foo(){return this.bar();},
         	bar:function(){
         		console.log('obj bar');
         	}
         }
         var wrapper={
         	 bar:function(){
         	 	console.log('wrapper bar');
         	 }
         }
        Reflect.get(obj,'foo',wrapper);
        //这时候把this.bar修改为wrapper.bar,这时候打印wrapper bar

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值