2

var obj, method;

obj = {
  go: function() { console.log(this); }
};

(method = obj.go)()

NOTE: Fyodor's first comment to his answer is what helped me the most. As the topic suggests, this was more about the parentheses than this.

In the last line, what I understand is that the parentheses will force the code inside to run first, so method takes the value of the go property, which is a function.

The () then calls that function, which logs window to the console because it wasn't called as a method.

If instead of (method = obj.go)(), you do method = obj.go(), it will first run the go function, and method will take the value returned by it. Since go returns nothing, it will be undefined. The value printed by go will be obj.

What I don't understand is, why if I do (obj.go)() the this printed is obj and not window?

Considering how the other code works, I expected this code to work kind of like this: obj.go is evaluated first inside the parentheses and then the function is run as an IIFE (function() { console.log(this); })(). So since the function isn't called as a method of obj, the this defaults to window.

1

1 Answer 1

4

(method = obj.go)() evaluated in two steps.

  1. method = obj.go is evaluated and method var become equal to function go of object obj. Functions in JavaScript can be called as methods or as functions, so in general it doen't metter how you;ve defined function go.

  2. Then method() is called. As you didn't provided value for this (either by calling method function as method of some object or using bind or call it is called with this set to global object (in non strict mode) or to undefined (in strict mode)

When you call obj.go() this is set equal to obj (it is similar to use obj.go.call(obj) or method.call(obj)). If you call just method() this is equal to global object (similar to call obj.go.call(window))

EDIT

And to get obj as this with your example you can do such way

(method = obj.go.bind(obj))()

In this way you not only assign go function to variable method but create binding to specific this equal to obj

Good reading about function invocation and this in JavaScript

Sign up to request clarification or add additional context in comments.

4 Comments

I understand all of this. I understand why this is what it is in all of the cases you mentioned. What I don't understand is why is (obj.go)() the same as obj.go(), but (method = obj.go)() is not the same as method = obj.go(). Why are the parentheses ignored in (obj.go)()?
Parentheses like in many other languages control order of code execution. So for (obj.go)() internals of parentheses is evaluated first. It evaluated to obj.go as inside parentheses there is nothing to evaluate. Then obj.go() is called. When (method = obj.go)() is used there is method = obj.go inside parenthese, so here is something to evaluate. After evaluation method becomes equal to go method of obj and on second step just method() is called
It is simply down to the relative precedence of . () and =
Thank you @Fyodor. I understand now. If I could mark this particular comment as the answer I would, since it's what clarifies my specific doubt. So I'll just mark the whole thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.