JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
249: globalThis Explained
If you've spent any time writing libraries or utilities that need to run in both the browser and Node.js, you've likely run into the "global object" headache. You want to attach something to the global scope—maybe a configuration object or a telemetry hook—but the global object isn't actually the same thing everywhere. In the browser, it's window. In Node, it's global. If you're inside a Web Worker, it's self. It's a fragmented mess that forces us to write defensive, boilerplate-heavy code just to reference the root of the environment.
The dance of the environment check
For years, the standard "safe" way to handle this was to write a detection utility. You've probably seen this pattern in older open-source projects: a messy ternary operator or a series of if statements trying to guess where the code is currently executing. I used to do this all the time when building cross-platform validators.
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 root = getGlobal();
root.myAppConfig = { apiVersion: 'v2' };
Now, this works, but it's fragile. It relies on typeof checks to avoid throwing ReferenceError exceptions when a variable doesn't exist in that specific environment. It's a lot of cognitive load for something that should be a fundamental part of the language. Plus, it's just ugly. You're essentially writing a mini-polyfill for the environment itself before you can even get to your actual logic.
The simplicity of globalThis
This is exactly why globalThis was introduced. It provides a single, standardized property that always points to the global object, regardless of whether you're in a browser, a server, or a worker. No detection logic, no ternary operators, and no worrying about whether window is defined.
// No matter where this runs, it just works.
globalThis.myAppConfig = { apiVersion: 'v2' };
I like to think of globalThis as the "universal adapter" for JavaScript. By using it, you're telling the engine, "I don't care what the environment calls its root; just give me the root." It makes your code cleaner and significantly more portable. If you're writing a module that might be imported into a Vite project (browser) and a Jest test (Node), globalThis is the only sane way to handle global state.
When to actually use it
A word of caution: just because you can easily access the global scope doesn't mean you should be polluting it. In modern development, we prefer modules and dependency injection. However, there are legitimate cases—like creating a global polyfill, setting up a global error handler, or configuring a library that needs to be accessible across multiple bundled chunks—where globalThis is the right tool. When those cases arise, stop writing environment checks and just use the standard.
📋 Practical Task
Refactoring the Cross-Platform Logger
You have been handed a legacy logging utility designed to work in both Node.js and the browser. Currently, it uses a clunky detection function to attach the logger to the global scope. Your task is to refactor this utility to use globalThis, removing the need for the detectGlobal helper function entirely.
// Current Legacy Code
function detectGlobal() {
if (typeof window !== 'undefined') return window;
if (typeof global !== 'undefined') return global;
return typeof self !== 'undefined' ? self : {};
}
const root = detectGlobal();
root.appLogger = {
log: (msg) => console.log(`[LOG]: ${msg}`),
error: (msg) => console.error(`[ERROR]: ${msg}`)
};
// Test it
appLogger.log('System initialized');
Goal: Rewrite the code so that the appLogger is attached to the global scope using globalThis in a single line of assignment, eliminating the detectGlobal function.
There are no comments for now.