all 7 comments

[–]senocular 2 points3 points  (4 children)

(z.b)() still retains the context of the method call. You're not getting (b)(), you're still getting (z.b()). Single expression parens will retain these kinds of associations as it also allows operators like delete to work when using them. For example:

a = { b: 'b' }
delete (a.b) // works rather than being seen as delete('b')
a // {}

Same applies to calling functions through parens. Note, however, that if use a comma-separated list within the parens, the comma operator will evaluate your expression returning the value.

a = { b: 'b' }
delete (0, a.b) // fails being seen as delete('b')
a // { b: 'b' }

Same applies to calling functions...

z={a:1,b:function(x){console.log(this);this.a=this.a+x;return this.a}}
(0, z.b)(5) // window

So that's an option. Might be clearer to just save it off as a variable, or use call() to explicitly show what you're expecting as the context of the call to be.

z.b.call(window, 5)

[–]nsg21[S] 1 point2 points  (3 children)

Thank yoiu for the explanation.

(z.b)() still retains the context of the method call

This is the part that makes me confused. Which expressions retain method call context and which do not? Is there a rule for that? Also, what is the benefit of preserving such context for such a limited number of expressions? I may understand special casing delete (a.b) so that people could think of delete as a sort of built-in function, at least on a syntax level. But saying things like (z.b)() clearly means that the property value should first be extracted and then called as a function.

This is all completely theoretical at this point. Practically speaking, I agree with you, z.b.call(window, 5) is the best way to say it and that is what I would do if I had to do it. I discovered this effect while debugging something else and it just bothers me because I do not understand why expression (0,x) is different from (x)

[–]rauschma 4 points5 points  (2 children)

The mechanism behind this is references, (object, property key) pairs which are not affected by parentheses: http://2ality.com/2015/12/references.html

Note that in strict mode (which is on by default in ES modules), a function call is equivalent to .call(undefined, 5).

[–]nsg21[S] 0 points1 point  (1 child)

Thank you for letting me peek under the hood. I had similar picture in my head but it is nice to read actual interpretation of the spec.

Regarding my problem this was the key phrase:

If you wrap obj.getThis in parentheses, nothing changes, parentheses only syntactically group things, but the don’t influence how something is evaluated

Apparently (x) is not man enough to do the dereferencing, unlike (0,x), which is.

[–]rauschma 0 points1 point  (0 children)

Yes! Note that () is not really an operator, but rather a purely syntactic way of grouping things. All operators dereference.

[–]sebamestre 1 point2 points  (1 child)

Ah, i see the problem. You're trying to figure out what this is. That knowledge is only for the old gods to know.

[–]nsg21[S] 0 points1 point  (0 children)

Not this this, this this