Calling function with window scope explanation (0, function(){})()

I am curious as to why this works:

var c = {
    d: function myFunc() {
        console.log(this === window);   
    }
};
var a = {
    b: function() {
        console.log(this === a);
        (0,c.d)();
        c.d();
    }
};
a.b();

Console output:

True
True
False

So it seems to be that (0, c.d)() is the same as c.d.call(window), but I cannot seem to find much about why or how this works. Can anyone explain?

From: Closure Compiler Issues

Fiddle: http://jsfiddle.net/wPWb4/2/


Solution 1:

If you write multiple expressions separated by a comma (,), then all expressions will be evaluated, but you will end up with the value of the last expression:

var x = (1,2,3);
console.log(x); // this will log "3"

Now (0,c.d) is an expression that will return the function c.d, but now c is not the this of the function anymore. This means that this will point to the global object (window), or remain undefined in strict mode. You would get the same effect with any of these:

var f = function(x) { return x; };
f(c.d)();

Or just

var f = c.d;
f();

Solution 2:

The expression (0, myFunc) is equivalent to just myFunc. The comma operator takes multiple expressions, evaluate them, and returns the last expression, so (0, myFunc) returns just myFunc.

Now, in your b method, this is equal to a because b is attached to a. In other words, b can be called by a.b(). However, myFunc is not attached to a (you can't call myFunc by a.myFunc()), so in myFunc, this can't be a. In fact, myFunc is called without setting its this so it defaults to the global object window (or remains undefined in strict mode), and therefore its this is equal to window.

You might be wondering what the point of the (0, listeners[i])() is, then, when they could have just written listeners[i](). Consider this code that creates an array with two elements, both functions:

var listeners = [
    function () { alert(this); },
    function () { alert(this); }
];

When you call listeners[0](), then in the listeners[0] function, this is equal to listeners, because 0 is attached to listeners, just like how b was attached to a. However, when you call the function by (0, listeners[0])(), listeners[0] is "decoupled" from the listeners array.* Since the decoupled function no longer is attached to anything, its this is the global object window.

*It's as if you wrote:

var temp = listeners[0];
temp();