Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API
设计目的
(1) 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上
现阶段,某些方法同时在 Object 和 Reflect 对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。
(2) 修改某些 Object 方法的返回结果,让其变得更合理
(3) 让 Object 操作都变成函数行为
与 Proxy 对象的关联
Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。
特别点
get 中的 receiver 参数
Reflect.get(target, name, receiver) 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回 undefined。
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
}
Reflect.get(myObject, 'foo') // 1
Reflect.get(myObject, 'bar') // 2
Reflect.get(myObject, 'baz') // 3如果 name 属性部署了读取函数(getter),则读取函数的 this 绑定 receiver。
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
};
var myReceiverObject = {
foo: 4,
bar: 4,
};
Reflect.get(myObject, 'baz', myReceiverObject) // 8set 中的 receiver 参数
Reflect.set 方法设置 target 对象的 name 属性等于 value。
var myObject = {
foo: 1,
set bar(value) {
return this.foo = value;
},
}
myObject.foo // 1
Reflect.set(myObject, 'foo', 2);
myObject.foo // 2
Reflect.set(myObject, 'bar', 3)
myObject.foo // 3如果 name 属性设置了赋值函数,则赋值函数的 this 绑定 receiver。
var myObject = {
foo: 4,
set bar(value) {
return this.foo = value;
},
};
var myReceiverObject = {
foo: 0,
};
Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1注意,如果 Proxy 对象和 Reflect 对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了 receiver,那么 Reflect.set 会触发 Proxy.defineProperty 拦截。
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上面代码中,Proxy.set 拦截里面使用了 Reflect.set,而且传入了 receiver,导致触发 Proxy.defineProperty 拦截。这是因为 Proxy.set 的 receiver 参数总是指向当前的 Proxy 实例(即上例的 obj),而 Reflect.set 一旦传入 receiver,就会将属性赋值到 receiver 上面(即 obj),导致触发 defineProperty 拦截。如果 Reflect.set 没有传入 receiver,那么就不会触发 defineProperty 拦截