In the evolving landscape of JavaScript, which spans web browsers, server-side environments like Node.js, and specialized runtimes like WebWorkers, accessing the “global object” was historically a fragmented and frustrating task. The introduction of globalThis in ES2020 (ES11) finally provided a unified, environment-agnostic way to access the global scope.
1. The Historical “Global Object” Fragmentation
Before globalThis, developers had to write “ponyfills” or complex detection logic because the name of the global object changed depending on where the code was executing:
- In Browsers: The global object is
window(or sometimesselforframes). - In Node.js: The global object is
global. - In Web Workers: The global object is
self. - In Shells (like V8’s d8): The global object is
thisat the top level.
This inconsistency made writing universal (isomorphic) JavaScript libraries difficult. A typical utility might start with this cumbersome check:
JavaScript
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
2. What is globalThis?
globalThis is a standard global property that returns the global this value, which is the same as the global object in the current environment.
Regardless of whether your code is running in a Chrome tab, a Node.js backend, or a background worker, globalThis will always point to the correct root context. It is a read-only property that cannot be deleted or reconfigured.
Example of Universal Access
JavaScript
// In a browser console
console.log(globalThis === window); // true
// In Node.js
console.log(globalThis === global); // true
// In a Web Worker
console.log(globalThis === self); // true
3. Practical Use Cases
A. Universal Library Development
If you are writing a library meant to be consumed by both frontend and backend developers (isomorphic JavaScript), globalThis allows you to attach or check for global properties without environment-specific logic.
// A universal logging utility
if (!globalThis.myAppConfig) {
globalThis.myAppConfig = { debug: true };
}
B. Feature Detection (Polyfilling)
globalThis is the ideal anchor for feature detection. If you want to check if a modern API like fetch is available, using globalThis is cleaner and safer than checking window.fetch, which might throw an error in non-browser environments.
if (globalThis.fetch) {
// Use native fetch
} else {
// Load a polyfill
}
4. Security and “Shadowing”
One of the subtle advantages of globalThis is that it is a read-only property of the global object (in most implementations). This prevents code from accidentally (or maliciously) overwriting it, which could break third-party scripts that rely on it to find standard APIs.
However, be aware that you can still “shadow” globalThis within a specific block or function scope:
{
const globalThis = "I am a string now";
console.log(globalThis); // "I am a string now"
}
5. Compatibility and Polyfilling
Since globalThis was introduced in 2020, it is supported in all modern browsers and Node.js (version 12+). For legacy environments (like Internet Explorer), a robust polyfill is required.
Because of the complexity of the global object, the most reliable way to polyfill it involves a self-invoking function that tries to find the global context through various known properties:
// Simplified polyfill concept
if (typeof globalThis === 'undefined') {
(function() {
Object.defineProperty(Object.prototype, '__magic__', {
get: function() { return this; },
configurable: true
});
__magic__.globalThis = __magic__;
delete Object.prototype.__magic__;
}());
}
