var a = 1;
var b = {
a : 2,
c : function () {
console.log(this.a);
}
};
b.c(); // logs 2
(b.c)(); // logs 2
(0, b.c)(); // logs 1
The fi
Refer to Indirect eval call, which gives more details about it.
( 0 , b.c ) ( )
|____| |_____| |_____|
Literal Operator Identifier
|_________________________|
Expression
|______________________________|
PrimaryExpression
|______________________________| |________|
MemberExpression Arguments
|________________________________________________|
CallExpression
We can use the comma operator to fashion an indirect call to b.c
which will force it to execute in the global context
, the value of a
is 1
in the global context
.
Also the result of (b.c = b.c)()
is 1
> (b.c = b.c)()
1
Speaking in terms of ECMAScript, this is because both — comma operator (in
(0, b.c)
example) and=
operator (in(b.c = b.c)
example) perform GetValue on its operands.
Other indirect call formats as below
> (b.c, b.c)()
1
> (1? b.c: 0)()
1
> (__ = b.c)()
1
You really have a nice corner case there! My take on it:
b
as the execution context.this
to the global object, but actually it's keeping it linked. Probably just so "casual" language users do not freak out.,
operator) the this
value is lost. This is because b.c
is a Property Reference
(deep rabbit hole details in the specification, here, courtesy of T.J.Crowder). So, you are actually passing around the function itself, no more bound to the declaring object. So when you call it this
is going to be passed in as the global object.See it this way: (object.function)()
gets simplyfied into object.function()
, because the enclosing parens are completely optional; (0, object.function)()
is parsed as (expression yielding a function)()
which is going to lose the object
binding to this
, because function is already unbound.
Really nice example!