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
and r3
expectedly contain correct result: "[object Object]"
, while r2
and r4
contain "[object Undefined]"
showing that m1
and m2
are not bound to object.
I can't fully comprehend how obj['toString']()
is executed. I always looked this way, (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.
Can anyone properly explain this behavior?
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
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
.
This is actually a "special" behavior of the grouping operator (...)
:
1. Return the result of evaluating Expression. This may be of type Reference.
NOTE This algorithm does not apply GetValue to the result of evaluating Expression. The principal motivation for this is so that operators such as
delete
andtypeof
may be applied to parenthesised expressions.
So, this operator specifically does not call GetValue
and thus does not return the function object itself but rather the whole reference, so that operations which expect a reference still work.
A Reference is basically an encapsulation of a value with an optional "base value" which is the object in case of a property access.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With