var obj = {};
var r1 = (obj[\'toString\'])();
var m1 = obj[\'toString\'];
var r2 = m1();
var r3 = (obj.toString)();
var m2 = obj.toString;
var r4 = m2();
>
Turns out that function invocation operator looks back on what is the context. I would expect operator to not know where operands come from.
In fact, it does know.
In the EcmaScript specification this is described by the property accessor operators (and a few similar operations) to return a "Reference object" that holds exactly this information: the context on which the property was accessed. Any "normal" operations will usually just get the reference's value - including the assignment operators, which do dissolve the reference in your case.
The call operator uses this to make method calls special:
- Let
refbe the result of evaluatingMemberExpression. which may return aReference- Let
funcbe 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
LetthisValuebe GetBase(ref). <- here the method context is fetched- Else, the base of
refis an Environment Record
… which basically describes variables inside awithstatement- Else, Type(
ref) is notReference.
LetthisValuebeundefined.