发布于 2016-08-27 11:18:52
反射和代理有完全不同的目的和不同的功能。
Proxy对象用于定义基本操作(例如属性查找、赋值、枚举、函数调用等)的自定义行为。
反射是一个内置对象,它为可拦截的JavaScript操作提供方法。这些方法与代理处理程序的方法相同。
我意识到你可能已经读过了,所以我会用一个例子来进一步解释。
假设你有一个对象:
const obj = {
a: 'foo',
b: 'bar',
};您可以使用属性访问器访问属性a,如下所示:
console.log(obj.a); // 'foo'您可以使用Reflect.get()方法进行同样的操作:
console.log(Reflect.get(obj, 'a')); // 'foo'还可以使用代理构造函数创建该对象的代理。我们将使用get处理程序来拦截所有属性查找。
const proxy = new Proxy(obj, {
get(target, property) {
return property in target ? target[property] : 'default';
},
});现在,使用属性访问器或Reflect.get()获取未定义的属性将导致字符串'default'
console.log(proxy.c); // 'default'
console.log(Reflect.get(proxy, 'c')); // 'default'代理和反射可以很好地协同工作。例如,您可以使用create创建一个具有非op get处理程序的代理:
new Proxy(obj, {
get: Reflect.get,
});发布于 2022-03-19 03:47:14
Proxy是一个对象的包装器,它将对对象的操作转发给对象,可以选择捕获其中的一些操作。高级代理对象允许您创建一个对象,该对象可以用来代替原始对象,但可以重新定义基本的对象操作,如获取、设置和定义属性。

Reflect API是用来补充代理的。内部方法如[[Get]]、[[Set]]等都是规范的,不能直接调用.更高级的Reflect对象使这在某种程度上成为可能。
因此,Proxy是一个包装器,可用于拦截对象上的基本操作(如[[Get]]和[[Set]]),而Reflect为这些基本操作(如[[Get]]和[[Set]])提供了最小的包装器,这样我们就可以直接调用它们(通常是从陷阱内部)。
对于每一个可由Proxy标记的内部方法,在Reflect中都有相应的方法,其名称和参数与代理陷阱相同。(!Important)
让我们看看这个例子,来演示它是如何有用的。
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return Reflect.get(target, prop, receiver);
// return target[prop];
}
});
alert(userProxy.name); // Guest在上面的示例中,在get陷阱中,return Reflect.get(target, prop, receiver);和return target[prop];都将打印相同的输出(Guest)。
让我们以一个稍微复杂一些的例子来说明为什么Reflect.get更好,为什么get/set有第三个参数receiver。
让我们创建一个对象admin,它继承自user
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return target[prop]; // (*) target = user
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
// Expected: Admin
alert(admin.name); // outputs: Guest (?!?)阅读相关的admin.name应该返回"Admin",而不是"Guest"!
问题实际上是在代理中,在行(*)中。
admin.name时,由于admin对象本身没有这样的属性,所以搜索就会找到它的原型。userProxy。name属性时,它的高级get陷阱触发并从原始对象返回它,并在行(*)中以target[prop]形式返回。对target[prop]的调用,当prop是一个getter时,在上下文this=target中运行其代码。因此,结果是this._name从原来的对象target,也就是:来自于user。要解决这个问题,我们需要将正确的this传递给getter。receiver,get陷阱的第三个参数使正确的this被传递给一个getter (在我们的例子中是admin)。对于一个常规函数,我们可以使用call/apply来绑定this值,但是我们不能对getter这样做,因为它不是called,而是访问的。
这是Reflect有用的地方。请记住,对于每一个内部方法,都是由Proxy标记的,在Reflect中有一个对应的方法,其名称和参数与代理陷阱相同。
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) { // receiver = admin
return Reflect.get(target, prop, receiver); // (*)
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
alert(admin.name); // Admin有关详细解释,请参阅Ilya:代理和反映的这篇精彩文章。
https://stackoverflow.com/questions/39179743
复制相似问题