Why Global Scope?
It’s likely no surprise that most applications are composed of multiple (sometimes many!) individual JS files. So how exactly do all those separate files get stitched together in a single runtime context by the JS engine?Three Main Ways
With respect to browser-executed applications, there are three main ways:-
ES Modules: Files are loaded individually by the JS environment. Each module
imports references to whichever other modules it needs to access. The separate module files cooperate exclusively through these shared imports, without needing any shared outer scope. - Bundled Files: If you’re using a bundler, all files are typically concatenated together before delivery to the browser. Some mechanism is necessary for each piece to register a name to be referred to by other pieces.
- Global Scope: Whether a bundler tool is used or files are simply loaded individually, if there is no single surrounding scope, the global scope is the only way for them to cooperate.
What Lives in Global Scope
In addition to accounting for where an application’s code resides during runtime, the global scope is also where: JS exposes its built-ins:- Primitives:
undefined,null,Infinity,NaN - Natives:
Date(),Object(),String(), etc. - Global functions:
eval(),parseInt(), etc. - Namespaces:
Math,Atomics,JSON - Friends of JS:
Intl,WebAssembly
console(and its methods)- The DOM (
window,document, etc) - Timers (
setTimeout(..), etc) - Web platform APIs:
navigator,history, geolocation, WebRTC, etc.
Node also exposes several elements “globally,” but they’re technically not in the
global scope: require(), __dirname, module, URL, and so on.Where Exactly is this Global Scope?
It might seem obvious that the global scope is located in the outermost portion of a file; that is, not inside any function or other block. But it’s not quite as simple as that. Different JS environments handle the scopes of your programs, especially the global scope, differently.Browser “Window”
With respect to treatment of the global scope, the most pure environment JS can be run in is as a standalone .js file loaded in a web page environment in a browser.<script> tag, a <script src=..> script tag, or even a dynamically created <script> DOM element. In all three cases, the studentName and hello identifiers are declared in the global scope.
That means if you access the global object (commonly, window in the browser), you’ll find properties of those same names there:
Globals Shadowing Globals
An unusual consequence of the difference between a global variable and a global property of the same name is that, within just the global scope itself, a global object property can be shadowed by a global variable:let declaration adds a something global variable but not a global object property. The effect then is that the something lexical identifier shadows the something global object property.
DOM Globals
One surprising behavior in the global scope you may encounter with browser-based JS applications: a DOM element with anid attribute automatically creates a global variable that references it.
What’s in a (Window) Name?
Another global scope oddity in browser-based JS:window.name is a pre-defined “global” in a browser context; it’s a property on the global object. The truly surprising behavior is that even though we assigned the number 42 to name, when we retrieve its value, it’s a string "42"! In this case, the weirdness is because name is actually a pre-defined getter/setter on the window object, which insists on its value being a string value.
Web Workers
Web Workers are a web platform extension on top of browser-JS behavior, which allows a JS file to run in a completely separate thread from the thread that’s running the main JS program. Since a Web Worker is treated as a wholly separate program, it does not share the global scope with the main JS program. However, the browser’s JS engine is still running the code, so we can expect similar purity of its global scope behavior. In a Web Worker, the global object reference is typically made usingself:
var and function declarations create mirrored properties on the global object (aka, self), where other declarations (let, etc) do not.
Developer Tools Console/REPL
With respect to our discussions here about scope, such observable differences in behavior may include:- The behavior of the global scope
- Hoisting
- Block-scoping declarators (
let/const) when used in the outermost scope
ES Modules (ESM)
ES6 introduced first-class support for the module pattern. One of the most obvious impacts of using ESM is how it changes the behavior of the observably top-level scope in a file.studentName and hello are not global variables. Instead, they are module-wide, or if you prefer, “module-global.”
In a module there’s no implicit “module-wide scope object” for these top-level declarations to be added to as properties. This is not to say that global variables cannot exist or be accessed in such programs. It’s just that global variables don’t get created by declaring variables in the top-level scope of a module.
Node
One aspect of Node that often catches JS developers off-guard is that Node treats every single .js file that it loads, including the main one you start the Node process with, as a module. The practical effect is that the top level of your Node programs is never actually the global scope. Node has from its beginning supported a module format referred to as “CommonJS”:var and function declarations are contained in that wrapping function’s scope, not treated as global variables.
So how do you define actual global variables in Node? The only way to do so is to add properties to another of Node’s automatically provided “globals,” which is called global. global is a reference to the real global scope object, somewhat like using window in a browser JS environment.
Global This
Reviewing the JS environments we’ve looked at so far, a program may or may not:- Declare a global variable in the top-level scope with
varorfunctiondeclarations—orlet,const, andclass - Also add global variables declarations as properties of the global scope object if
varorfunctionare used - Refer to the global scope object with
window,self, orglobal
globalThis. We could even attempt to define a cross-environment polyfill:

