var obj = {};
var r1 = (obj['toString'])();
var m1 = obj['toString'];
var r2 = m1();
var r3 = (obj.toString)();
var m2 = obj.toString;
var r4 = m2();
r1
和 r3
应该包含正确的结果:"[object Object]"
,而 r2
和 r4
包含 "[object Undefined]"
表明 m1
和 m2
没有绑定(bind)到对象。
我无法完全理解 obj['toString']()
是如何执行的。我总是这样看,(obj['toString'])()
-> (function obj)()
。事实证明,函数调用运算符会回顾上下文。我希望运算符不知道操作数的来源。
谁能正确解释这种行为?
最佳答案
Turns out that function invocation operator looks back on what is the context. I would expect operator to not know where operands come from.
事实上,它确实知道。
在 EcmaScript 规范中,这由 property accessor operators 描述(以及一些类似的操作)返回一个“Reference object”,它包含了这个信息:属性被访问的上下文。任何“正常”操作通常只会获取引用的值 - 包括 assignment operators ,这确实会解除您案例中的引用。
call operator使用它来使方法调用变得特殊:
- Let
ref
be the result of evaluatingMemberExpression
. which may return aReference
- Let
func
be GetValue(ref)
. which fetches the actual function object - you see this operation a lot in the spec- … fetch arguments, do some type assertions
- If Type(
ref
) isReference
, then
- If IsPropertyReference(
ref
) is true, then
LetthisValue
be GetBase(ref
). <- here the method context is fetched- Else, the base of
ref
is an Environment Record
… which basically describes variables inside awith
statement- Else, Type(
ref
) is notReference
.
LetthisValue
beundefined
.
关于javascript - JS 绑定(bind)函数和函数调用运算符的性质,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25609927/