跳到主要内容

认识

2023年08月17日
柏拉文
越努力,越幸运

一、认识


Reflect是一个内置的对象,字面意思是反射。它提供拦截JavaScript操作的方法。这些方法与proxy handlers(en-US)的方法相同。Reflect不是一个函数对象,因此它是不可构造的。

我们Object已经可以实现这些操作了,为什么还需要有Reflect呢?

  • 这是因为在早期ECMA规范中没有考虑到这种对对象本身的操作如何设计更加规范。所以将这些API放到了Object上面。但是Object 仅仅是一个构造函数,这个操作实际上放到他身上并不合适。
  • 类似于indelete操作符,让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);