Skip to main content
Dublin Library

The Publishing Project

globalThis in JavaScript

 

`globalThis` is a universal accessor for the global object in JavaScript. It provides a reliable, standard way to access global variables and functions regardless of the environment executing the code. This post explains the purpose of `globalThis`, how it unifies access to the global scope across different JavaScript environments, and how to use it effectively in JavaScript and TypeScript projects. It also covers polyfilling `globalThis` for legacy environments. ## Purpose and functionality Before `globalThis`, the global object had different names depending on the runtime environment. Code designed to run in multiple environments—such as isomorphic libraries or cross-platform utilities required complex workarounds to find the global object. `globalThis` standardizes this reference. When developers call `globalThis`, it points directly to the environment's global scope. Properties assigned to it become available globally. ### Legacy global references `globalThis` does not deprecate older global references, but it eliminates the need for environment-checking fallback logic. It unifies the following environment-specific global objects: | Environment | Legacy Global Object Reference | | --- | --- | | Web Browsers | window, frames, self | | Web Workers | self | | Node.js | global | | Standalone JavaScript | this (Note: this is undefined in strict-mode functions) | ### Browser references: window, frames, and self In browser environments, developers historically used three separate references: * **window**: The standard global object in a browser's main thread. It represents the browser window or tab containing the DOM document. * **frames**: A property of the window that returns the window itself (window === frames). * **self**: In a standard browser window, self points to the window object. In Web Workers, which lack access to the DOM and the window object, developers use self (specifically WorkerGlobalScope) to reference the global context. Historically, developers used the following pattern to find the global object safely across these contexts: **JavaScript** ```js // The legacy workaround const 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'); }; const myGlobal = getGlobal(); ``` **TypeScript** ```ts // The legacy workaround const getGlobal = (): any => { 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'); }; const myGlobal = getGlobal(); ``` With `globalThis`, a single native keyword replaces this entire block of code. ### Cross-environment compatibility Introduced in ECMAScript 2020 (ES11), `globalThis` works consistently across modern JavaScript environments: * **Browsers**: Chrome 71+, Firefox 65+, Safari 12.1+, Edge 79+ * **Server/Runtimes**: Node.js (v12.0.0+), Deno, Bun * **Workers**: Web Workers, Service Workers ## Strict mode and ES modules Historically, developers relied on the this keyword at the global scope to access the global object. However, strict mode and ES modules (ESM) alter this behavior to prevent accidental global variable creation. In a standard script, the top-level this refers to the global object. In strict mode ("use strict";) or inside an ES module, the top-level this evaluates to undefined. `globalThis` resolves this inconsistency by bypassing the execution context's this binding to provide a guaranteed reference to the global object. **JavaScript** ```js // JavaScript - ES Module or Strict Mode context "use strict"; console.log(this); // Outputs: undefined console.log(globalThis); // Outputs: the global object (e.g., Window or global) // Attempting to set a global variable using legacy patterns try { this.myVar = 'Hello'; // Throws TypeError } catch (e) { console.error(e.message); } // Safely setting a global variable globalThis.mySafeVar = 'Hello'; console.log(globalThis.mySafeVar); // Outputs: 'Hello' ``` **TypeScript** ```ts // TypeScript - ES Module or Strict Mode context "use strict"; console.log(this); // Outputs: undefined console.log(globalThis); // Outputs: the global object // Attempting to set a global variable using legacy patterns causes a type error. // Safely setting a global variable requires augmenting the global scope first, // or bypassing types (not recommended): (globalThis as any).mySafeVar = 'Hello'; ``` ## Limitations of globalThis While `globalThis` provides a unified reference, consider these contextual behaviors: * **Realm-specific scope**: `globalThis` points to the global object of the current JavaScript realm. Inside an <iframe>, `globalThis` refers to the iframe's window object, not the parent document. * **Security restrictions**: `globalThis` does not bypass Content Security Policy (CSP) rules. * **Frozen global objects**: In secure environments like Secure ECMAScript (SES), where the environment freezes the global object using Object.freeze(), developers cannot assign new properties to `globalThis`. ## Polyfilling `globalThis` To support older environments like Internet Explorer 11, developers must polyfill `globalThis`. Note that a robust polyfill is complex because modern bundlers often enforce strict mode, and CSP rules frequently block the Function('return this')() workaround. ### JavaScript polyfill Include this code at the start of your application entry point: ```js (function() { if (typeof globalThis !== 'undefined') return; var getGlobalObject = function() { if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global !== 'undefined') return global; return Function('return this')(); }; var globalObj = getGlobalObject(); if (globalObj) { globalObj.globalThis = globalObj; } else { throw new Error('Unable to locate the global object.'); } })(); ``` The code will first check if `globalThis` is already defined. If not, it attempts to find the global object using the legacy checks. If it successfully finds the global object, it assigns it to `globalThis`. If it cannot find the global object, it throws an error. We run the code in an immediately invoked function expression (IIFE) to avoid polluting the global scope with temporary variables. ### TypeScript configuration In TypeScript, update your tsconfig.json to include ES2020 in the lib array so the compiler recognizes `globalThis`. ```json { "compilerOptions": { "target": "ES5", "lib": [ "DOM", "ES5", "ScriptHost", "ES2020" ] } } ``` ## Code examples **Using `globalThis` in JavaScript** ```js globalThis.appConfig = { theme: 'dark', debugMode: true }; function readConfig() { if (globalThis.appConfig.debugMode) { console.log('Running in debug mode.'); } } readConfig(); ``` **Using `globalThis` in TypeScript** In TypeScript, developers must augment the global scope to ensure type safety when adding custom properties to `globalThis`. ```ts interface AppConfig { theme: string; debugMode: boolean; } // Augment the global scope declare global { var appConfig: AppConfig; } `globalThis`.appConfig = { theme: 'dark', debugMode: true }; function readConfigTS(): void { if (`globalThis`.appConfig.debugMode) { console.log('Running in debug mode.'); } } readConfigTS(); ```

Edit on Github