global
globalThis
” in “JavaScript for impatient programmers”.The ECMAScript proposal “global
” by Jordan Harband is currently at stage 3. It provides a new standard way of accessing the global object.
The following are a few popular ways of referring to the global object:
window
: is the classic way of referring to the global object. But it doesn’t work in Node.js and in Web Workers.self
: is available in Web Workers and browsers in general. But it isn’t supported by Node.js. Some people take self
appearing in code, as a sign that that code works in both Web Workers and normal browser settings.global
: is only available in Node.js. Until now!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), its this
refers to the global object in non-strict mode. In strict mode, it is undefined
.new Function('return this')()
: works in both strict mode and sloppy mode, because the parameters of new 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 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
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
declarationsIn 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.
The proposal’s author, Jordan Harband, has written a polyfill for it.
Using it with CommonJS syntax:
// Computing the value of `global`
var global = require('system.global')();
// Shimming `global` (installing it globally)
require('system.global/shim')();
Using it with ES6 module syntax:
// Computing the value of `global`
import getGlobal from 'system.global';
const global = getGlobal();
// Shimming `global` (installing it globally)
import shim from ‘system.global/shim’; shim();
The package always uses the “most native” approach available (global
on Node.js etc., window
in normal browser contexts, etc.).
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')();
}