我正在阅读You Don't Know JS: ES6 & Beyond。我发现了一些混淆的措辞,如
我们将一个get(..)处理程序声明为处理程序对象上的命名方法(代理(...)的第二个参数),它接收对目标对象(obj)的引用,即键属性名称(&# 34; a"),以及self / receiver / proxy(pobj)。
我的问题是接收器的意思是什么,它的名字来自哪里?
好像我有一个带有成员函数的对象跳转:
var a = { jump: function(){console.log('jump!')} };
如果我运行a.jump();
,那么a就是接收者。
是这样的吗?如果我错了,请纠正我。 非常感谢!
对于阅读同一本书的人 ,当您来到Proxy First, Proxy Last部分时,您可以在代码中添加一行以更清晰关于获取陷阱中的上下文的图片。
var handlers = {
get(target,key,context) {
console.log(greeter === context); //true, this line added
return function() {
context.speak(key + "!");
};
}
},
catchall = new Proxy( {}, handlers ),
greeter = {
speak(who = "someone") {
console.log( "hello", who );
}
};
// setup `greeter` to fall back to `catchall`
Object.setPrototypeOf( greeter, catchall );
greeter.speak(); // hello someone
greeter.speak( "world" ); // hello world
greeter.everyone(); // hello everyone!
正如您所看到的,由于作者,上下文的get陷阱的第三个参数的命名,接收器可以根据词法代码 - greeter.everyone();
而变化。有关更好的理解,请参阅下面的Oriol非常详细的答案。谢谢你们!
答案 0 :(得分:9)
接收器是发生属性查找的对象。
是的,如果你使用a.jump
,a
就是接收者。
只有在发生属性查找时才能执行任意代码时,该概念才有意义。基本上,这意味着:
访问者属性。
您可以使用getter或setter中的this
来访问接收器。接收器通常是您定义属性的对象,或者是从其继承的另一个对象。
var target = {
get getReceiver() { return this; }
};
target.getReceiver; // target
var inherits = Object.create(target);
inherits.getReceiver; // inherits
内置示例是__proto__
,定义为Object.prototype
的属性,但希望在其他对象(接收方)上获取或设置。
代理对象
代理对象允许您定义get
或set
陷阱,当您尝试获取或设置代理的任何属性时,这些陷阱会运行一个函数。接收器作为该函数的参数提供。接收器通常是Proxy对象本身,或者是从它继承的对象。
var proxy = new Proxy({}, {
get: function(target, property, receiver) {
return receiver;
}
});
proxy.getReceiver; // proxy
var inherits = Object.create(proxy);
inherits.getReceiver; // inherits
注意,您可以使用Reflect.get
或Reflect.set
来指定任意接收器:
Reflect.get(target, "getReceiver", arbitraryValue); // arbitraryValue ¹
Reflect.get(proxy, "getReceiver", arbitraryValue); // arbitraryValue
¹如果在非严格模式下定义了getter,它将是Object(arbitraryValue)
。
名称“receiver”来自规范,请参阅Object Internal Methods and Internal Slots
[[Get]]( propertyKey , Receiver )→任何
从此对象返回其键为 propertyKey 的属性的值。如果必须执行任何ECMAScript代码来检索 属性值, Receiver 用作此值时 评估代码。
[[Set]]( propertyKey , value , Receiver )→ Boolean
将键为 propertyKey 的属性的值设置为value。如果必须执行任何ECMAScript代码来设置属性值, 在评估代码时, Receiver 用作 this 值。如果设置了属性值,则返回 true ;如果设置属性值,则返回 false 无法设定。
答案 1 :(得分:2)
我花了一些时间试图弄清楚与Reflect.get
一起使用时,该“接收器”将被用作什么,并且可能毫无疑问,它们都和MDN explains一样:
receiver
可选
如果遇到吸气剂,则为目标调用提供this
的值。与Proxy
一起使用时,它可以是从target
继承的对象。
据我估计,基本上Reflect.get
中它起着决定性的作用是用于访问 getter 属性。例如,以下调用将返回2
,而不返回undefined
。
const obj = { get foo() { return this.bar; } };
Reflect.get(obj, "foo", { bar: 2 });
使用get foo()...
作为“接收者”来调用实际的getter({ bar: 2 }
)。如果没有Reflect.get
的第三个参数,接收者自然就隐含为对象本身,并且由于它没有bar
属性,因此返回undefined
。如果它定义了bar
属性,那么事情实际上会简单得多:
const obj = { bar: 1, get foo() { return this.bar } };
obj.foo; /// evaluates to 1
Reflect.get(obj, "foo"); /// evaluates to 1, equivalent to above
Reflect.get(obj, "foo", { bar: "soap" }) /// evaluates to, guess what, "soap"
我认为没有什么比这更多的了,反正没有Reflect.get
。