Search code examples
javascriptthisparentheses

How do parentheses affect code in JavaScript?


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.


Solution

  • (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