核心提示:前言:ES6 Proxy和Reflect是一个蛮有用的组合,这两个属性相辅相成。这篇文章是通过用这两个属性来写一个 简单的常用实例。也通过这个实例来说明Proxy和Reflect几个常用的方法。Pro...
前言:
ES6 Proxy和Reflect是一个蛮有用的组合,这两个属性相辅相成。这篇文章是通过用这两个属性来写一个 简单的常用实例。也通过这个实例来说明Proxy和Reflect几个常用的方法。
Proxy是什么?
Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,需要一种“元编程”,即对编程语言进行编程。可以理解为对目标对象设置“拦截”层,外界访问该对象必须先通过拦截层。因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词翻译为代理。
let proto = { set : function(obj, key,value){ console.log("setting"+${key}); } } let demo = new Proxy({},proto); demo.age = 100;//输出“setting age”
Reflect是什么?
Reflect对象设计目的有以下几个。
1.将Object对象的一些明显属于语言层面的方法放到Reflect对象上。
Object.defineProperty
Reflect.defineProperty
2.修改某些Object方法的返回结果,让其变得更合理。比如Object.defineProperty(obj, name, desc)在无法定义属性时会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
原来
try { Object.defineProperty(obj, name, desc); // property defined successfully } catch (e) { // possible failure (and might accidentally catch the wrong exception) }
重构后:
if (Reflect.defineProperty(obj, name, desc)) { // success } else { // failure }
3.让Object操作都编程函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj,name)和Refect.deleteProperty(obj,name)让它们变成了函数行为。
4.Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象找到相应的方法。Proxy是修改对象的行为,而Reflect是获取对象默认行为。
Rroxy和Reflect实例:
let proto = { 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}!'); return Reflect.set(target,key,value,receiver); }, apply:function(target,thisArg,args){//拦截调用方法 console.log('apply'); return Reflect.apply(target,thisArg,args); }, construct:function(target,thisArg,proxy){//拦截new console.log('construct'); return Relect.apply(target,thisArg,proxy); }, deleteProperty:function(target,key){//拦截删除元素 console.log('delete '+${key}); return Relect.deleteProperty(target,key); }, enumerate:function(target){//拦截for...in循环 console.log('enumerate') return Relect.enumerate(target) }, has(target,key){//隐藏某些属性,不被in操作符发现 if(key[0]==='_'){ console.log('has') return false; } return Relect.has(target,key) } } let demo = new Proxy({},proto); /*触发方法*/ demo.name;//getting name! demo.age = 100; //setting age! demo()//apply new demo()//construct delete demo.age //delete age var p = "asdf"; for(let x in p){}//enumerate; var q = "_123"; for(let x in q){}//has;