参考:ECMAScript 6 入门
为什么要设计Reflect?
将Object对象的一些明显属于语言内部的方法(比如
Object.defineProperty
),放到Reflect对象上。未来的新方法将只部署在Reflect对象上。让Object操作都变成函数行为。
解释:某些Object操作是命令式,比如name in obj
和delete obj[name]
,而Reflect.has(obj, name)
和Reflect.deleteProperty(obj, name)
让它们变成了函数行为。使用 Reflect 获取对象的默认行为。
解释:Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。- 我的理解:reflect 意思是反射。所以它的本意是调用原来对象上的方法(java 中也有 reflect,可以类比)
非重点:
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)
上面这些方法的作用,大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。下面是对它们的解释。
举例:
其实我对这个例子也没完全看懂
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
解释(我的猜测):
首先要明确 set 和 defineProperty 的区别
- 当属性已经存在的时候走 set 拦截
- 属性还不存在的时候定义先走 defineProperty 拦截
当执行obj.a
时,会走到 handler 的 set 方法,然后再执行到Reflect.set(target, key, value, receiver)
, receiver 代表的是 proxy 的实例。这句执行的时候,调用方法应该还是 p 对象的 set 方法,但是 set 方法里的 this 变成了 proxy 对象,相当于给 proxy 对象定义了一个新属性,所以会走 defineProperty 拦截
// 我对 set 方法的推测
set(value){
// 如果传入了 receiver,this 就变成了 proxy 对象;如果不传,就是 p 对象
this.a = value;
}