Maximus Maximus - 1 month ago 8
Javascript Question

Why parenthesis are ignored in the expression (o.method)()

I want to understand why the parenthesis around

o.method
in the expression

(o.method)()


are ignored and so it's behaving equally to
o.method()
, with execution context of
method
referencing
o
. I was expecting it to behave similarly to
(o.method || true)()
, where execution context inside
method
references global object.

If I evaluate
(o.method)
on its own, it returns reference to a standalone function not bound to any context. Simply rewriting it like this

var a = (o.method); a();


will have global context as expected. And I've just shortened the code by replacing
a
, and it produced different result.

Answer

I think it has to do with ES5 11.1.6:

11.1.6 The Grouping Operator # Ⓣ

The production PrimaryExpression : ( Expression ) is evaluated as follows:

  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 and typeof may be applied to parenthesised expressions.

Let's see how function invocation is done in JS:

The key point is that o.method is a Reference (as defined by the spec):

A Reference is a resolved name binding. A Reference consists of three components, the base value, the referenced name and the Boolean valued strict reference flag.

So, o.method is not a Function YET; it is basically [[o, "method", false]]. When invoked with an argument list, o.method(), the reference value is taken by GetValue, then the method invocation proceeds (as described in 11.2.3).

When you do (o.method)(), (o.method) is still a Reference - GetValue has still not been applied to it (per the quoted 11.1.6). So nothing changes.

When you do (o.method || true)(), || will apply GetValue to the left side (per 11.11) and produce a function value - not a Reference any more. Thus, it cannot be evaluated as a method invocation, since the information about the base and referenced name (that was present in Reference) is lost.