Finding the global object

One of the JavaScript common pitfalls is a problem finding the global object in a truly universal way. This is especially common for code not relying on a specific build system. When you're writing code that could be dropped in anyway, included with any module loader or build system, and loaded into any JS environment there isn't a whole lot you can count on. Not even how to access the global object.

The common mistake is to rely on 'this' outside of your functions definition. That works if your module has been included in the browser as a script tag, but if it's been built with a module loader, you have no idea what this outside of your function could be.

(function (win) { win.foo = 'bar' })(this) console.log(global.foo) // undefined console.log(exports.foo) // bar

When run in node, the code above does something unexpected, but interesting. Instead of putting the properties on the global object, it puts them on the exports object... If you run it in the browser directly, it will put foo on window. Useful in both cases, but not very portable.

(function () { var win = this win.foo = 'bar' })() console.log(global.foo) // bar console.log(exports.foo) // undefined

By assigning win to 'this' inside of our function, we can tell how our function was called, and thus know what the 'this' value should be. In node and the browser this fixes our function right up. But what if it was wrapped inside a function by a build system that uses strict mode?

// broken (function () { "use strict"; (function () { var win = this win.foo = 'bar' //TypeError: Cannot set property 'foo' of undefined })() })() console.log(global.foo) // we never console.log(exports.foo) // get here

Both of the approaches above have the same problem, strict mode effects all functions underneath them, so an outer strict mode wrapper made 'this' within stand alone function calls 'undefined' instead of the global object. This is specifically so functions have a harder time modifying the global object. It is a sensible thing to do, but it puts a damper on our plan.

When possible, the best way out of this is to require a simple module, designed to solve just this problem: global . The best part is that this is likely to be updated if a new environment comes out that isn't supported. Really though, Node probably should have just made window a reference to the global object...