2

Suppose I have an object:

var o = {
    prop: 3,
    method: function() {return this.prop}
}

I was expecting this

(o.method)()

to return undefined, however it returned 3 meaning that this is set to o inside method. Why is it so? If you evaluate (o.method) separately, it evaluates to a standalone function, so I expected this to reference global object. Why, for example, the difference exists here:

(o.method)() vs (o.method || true)()

I know that o.method() will use o as context, the question is specifically about accessing the function first like this (o.method) and then calling it.

Max Koretskyi
  • 85,840
  • 48
  • 270
  • 414
  • `o.method()` is a shortcut for `method.call(o);`. Does this help? – freakish Oct 31 '16 at 18:33
  • also, try : `var a = {prop: 'foo', fn: o.method}; a.fn();` the method is _bound_ to the object is it called on (i.e., `this` becomes the object that the function is called from) – njzk2 Oct 31 '16 at 18:38

1 Answers1

2

That's just how JavaScript's rules work. Unless you do some contortions, this usually means the thing before the . when you access the method prior to calling it. In this case, that's o.

The following statements are identical:

(o.method)();
o.method();
o.method.call(o);
o["method"]();

However, if you put the method on something else, it'll take on the meaning of the thing it's on:

var p = {prop: 42, method: o.method};
p.method(); // returns 42

var method = o.method;
var prop = 13;
method(); // returns 13

Note: As JavaScript grew to be much more than it was originally designed for, people realized that this probably wasn't the most intuitive way for this to work, so in ES6 if you use "Arrow Functions" (aka Lambda Functions) it won't rebind this.

StriplingWarrior
  • 135,113
  • 24
  • 223
  • 283
  • I agree with you answer, but you should also mention `=>` functions since they will behave as the OP expects. – Mobius Oct 31 '16 at 18:35
  • This applies to property lookup in general: `o["method"]()` does the same thing (and `foo.bar` is just syntactic sugar for `foo["bar"]`). – melpomene Oct 31 '16 at 18:37
  • thanks, please see my update. I formulated the question in an ambiguous way I guess initially – Max Koretskyi Oct 31 '16 at 18:43
  • @Maximus: See my update too, as well as the comments above. The function is bound based on where it came from in the JavaScript expression. That binding doesn't change unless you assign it to a different variable (or use `.call()`, `.bind()`, etc.) – StriplingWarrior Oct 31 '16 at 18:51
  • @StriplingWarrior, sorry, still not that. Can you explain the difference here `(o.method)() vs (o.method || true)()` Why the second example is parsed differently than the first one? – Max Koretskyi Oct 31 '16 at 18:52
  • @Maximus: That's a better question. It makes sense that `(o.method)()` is the same as `o.method()`, since the logical grouping operator's only effect is to help determine the order of operations, and the `.` accessor would already precede the method call in that statement. The real question (and one which I don't really know the answer to) is why the application of another operator like the `||` in your example changes the binding of the method chosen by that expression. I'm sure it's in the spec somewhere, but I don't know why they chose to specify that particular behavior. – StriplingWarrior Nov 01 '16 at 15:51
  • 1
    @StriplingWarrior, yeah, I figured this question is doomed to be misunderstood and so I asked [another one](http://stackoverflow.com/questions/40354642/why-parenthesis-are-ignored-in-the-expression-o-method). There is a great answer there explaining the behavior basing on the spec. – Max Koretskyi Nov 01 '16 at 16:05