认识
2023年08月17日
一、认识
Reflect是一个内置的对象,字面意思是反射。它提供拦截JavaScript操作的方法。这些方法与proxy handlers(en-US)的方法相同。Reflect不是一个函数对象,因此它是不可构造的。
我们Object
已经可以实现这些操作了,为什么还需要有Reflect
呢?
- 这是因为在早期
ECMA
规范中没有考虑到这种对对象本身的操作如何设计更加规范。所以将这些API
放到了Object
上面。但是Object
仅仅是一个构造函数,这个操作实际上放到他身上并不合适。 - 类似于
in
、delete
操作符,让JavaScript
看起来有一些奇怪
综上所述,在ES6
中我们新增了Reflect
。
二、精益求精
2.1 Reflect 存在的意义是什么? Reflect 解决了什么问题?
Proxy
拦截器中的 receiver
表示 Proxy
或者继承Proxy
的对象(表示代理对象本身或者继承与代理对象的对象)。在 Proxy
中配合 Reflect
使用, 可以正确的为拦截器传递上下文引用。
针对普通属性: 通过代理对象访问普通属性, 可以正确传递上下文引用, 普通属性中的 this
指向代理对象,这样是正确的指向。
const source = {
_a: '嘻嘻',
a() {
console.log(this); // this 指向 Proxy 代理对象
return this._a;
}
};
const proxy = new Proxy(source, {
get(target, key, receiver) {
return target[key];
},
set(target, key, value, receiver) {
target[key] = value;
return true;
}
});
console.log(proxy.a());
针对访问器属性: 通过代理对象访问访问器属性, 访问器属性中的 this
指向的是源对象, 而不是指向代理对象,这样是错误的指向。
const source = {
_a: '嘻嘻',
get a() {
console.log(this); // this 指向 源对象
return this._a;
}
};
const proxy = new Proxy(source, {
get(target, key, receiver) {
return target[key];
},
set(target, key, value, receiver) {
target[key] = value;
return true;
}
});
console.log(proxy.a);
由上所述,我们需要解决访问器属性中 this
上下文传递错误的情况, 需要配合 Reflect
使用, 解决如下:
const source = {
_a: '嘻嘻',
get a() {
console.log(this); // this 指向 Proxy 代理对象
return this._a;
}
};
const proxy = new Proxy(source, {
get(target, key, receiver) {
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
target[key] = value;
return true;
}
});
console.log(proxy.a);