The ECMAScript proposal “global
” by Jordan Harband is currently at stage 3. It provides a new standard way of accessing the global object.
Referring to the global object
The following are a few popular ways of referring to the global object:
- Global variables:
- Global variable
window
: is the classic way of referring to the global object. But it doesn’t work in Node.js and in Web Workers. - Global variable
self
: is available in Web Workers and browsers in general. But it isn’t supported by Node.js. Some people useself
to mark code that works in both Web Workers and normal browser contexts. - Global variable
global
: is only available in Node.js. Until now!
- Global variable
this
:this
in global scope: refers to the global object. The only problem is that Node.js modules and ES6 modules have their own scopes, which means that this approach doesn’t work there.this
during a function call in sloppy mode: If you call a function via a function call (and not a method call), itsthis
refers to the global object in non-strict mode. In strict mode, it isundefined
.new Function(‘return this‘)()
: works in both strict mode and sloppy mode, because the parameters ofnew Function()
are always evaluated in sloppy mode. There is one important caveat:eval
,new Function()
, etc. are not available if you use CSP (Content Security Policy). That makes this approach unsuited in many cases.
The proposal
The ECMAScript proposal standardizes the global variable global
for accessing the global object. It also standardizes that the global object must have Object.prototype
in its prototype chain. The following is already true in web browsers today:
> Object.prototype.isPrototypeOf(window) true
Best practices
The global object is now considered a mistake that javascript can’t get rid of, due to backward compatibility. It affects performance negatively and is generally a confusing feature.
ECMAScript 6 moves away from the global object by providing three new ways for declaring variables that don’t create global properties in global scope (as var
declarations and function declarations do):
let
declarationsconst
declarations- Class declarations
In other words: all properties of the global object are global variables, but not all global variables are properties of the global object. For example (executed in global scope):
> var foo; > ‘foo‘ in window true > let bar; > ‘bar‘ in window false
It is normally preferable to refer to global variables as variables and not as properties of, e.g.,window
. That has always worked on all JavaScript platforms.
Furthermore, starting with ES6 (and even before), most JavaScript code lives in modules and will thus never be in global scope.
Therefore, global
will mostly be relevant for polyfills.
A polyfill
The proposal’s author, Jordan Harband, has written a polyfill for it.
Using it with CommonJS syntax:
var global = require(‘system.global‘)();
Using it with ES6 module syntax:
import getGlobal from ‘system.global‘;
const global = getGlobal();
The package always uses the “most native” approach available (global
on Node.js etc.,window
in normal browser contexts, etc.).
Computing a reference to the global object
Internally, the polyfill uses the function getPolyfill()
to compute a reference to the global object. This is how that is achieved:
// polyfill.js
var implementation = require(‘./implementation‘);
module.exports = function getPolyfill() {
if (typeof global !== ‘object‘ || !global || global.Math !== Math
|| global.Array !== Array) {
return implementation;
}
return global;
};
// implementation.js
if (typeof self !== ‘undefined‘) {
module.exports = self;
} else if (typeof window !== ‘undefined‘) {
module.exports = window;
} else if (typeof global !== ‘undefined‘) {
module.exports = global;
} else {
module.exports = Function(‘return this‘)();
}