ES6 Proxy 和 Reflect 用法

前言:

ES6 Proxy和Reflect是一个蛮有用的组合,这两个属性相辅相成。这篇文章是通过用这两个属性来写一个 简单的常用实例。也通过这个实例来说明Proxy和Reflect几个常用的方法。


Proxy是什么?

Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,需要一种“元编程”,即对编程语言进行编程。可以理解为对目标对象设置“拦截”层,外界访问该对象必须先通过拦截层。因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy这个词翻译为代理。

let proto = {
    set : function(key,value){
        console.log(`setting ${key}=${value}`);
    }
}

let demo = new Proxy({},proto);
demo.age = 100;//输出“setting age=100”

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;

附:ES6转换ES2015

http://blog.csdn.net/rth362147773/article/details/78275551

你可能感兴趣的:(前端技术)