this in the Global Context
Introduction
this is not a variable you declare. It is a runtime value supplied when a function is called. In the global context, its value depends heavily on where the code runs: classic browser scripts, ES modules, Node wrappers, and Web Workers differ.
For interviews, the safe mental model is: never guess from the text alone; ask how the function is invoked. Top-level this is mostly an environment detail, while function-call this follows binding rules.
Why This Matters
Many senior-looking bugs come from assuming this means the surrounding object or the current file. Interviewers use global-context questions to test whether you can separate JavaScript language semantics from host-environment behavior. In production, this matters when moving code between browser scripts, ES modules, bundlers, Web Workers, and Node.
Theory
The interview-safe framing
At the top level, this is host and source-type dependent:
| Context | Typical top-level this |
|---|---|
| Classic browser script | The global object (window) |
| ES module in browser or Node | undefined |
| Node CommonJS file | module.exports, because Node wraps the file in a function |
| Web Worker | Environment-dependent enough that output puzzles should avoid printing it directly |
The important lesson is not memorising every host. The important lesson is learning that top-level this is not the same interview problem as function-call this.
The four binding rules
When a regular function executes, JavaScript determines this from the call site using these rules:
- Default binding — plain call:
fn(). In sloppy mode,thisis substituted with the global object; in strict mode,thisstaysundefined. - Implicit binding — property call:
obj.fn().thisisobj. - Explicit binding —
fn.call(obj),fn.apply(obj), orfn.bind(obj).thisis the supplied object, except arrows ignore it. - new binding —
new Fn(). A fresh object becomesthisinside the constructor.
Precedence
The rules have a useful precedence order:
new binding > explicit binding (call, apply, bind) > implicit binding > default binding.
A bound function called with new still uses the newly-created object as this. A method reference passed around without its object falls back to default binding unless it is bound or wrapped.
Strict mode changes default binding
Strict mode does not change implicit, explicit, or new binding. It changes the plain-call fallback. In strict mode, a plain call leaves this as undefined, which is safer because bugs fail loudly instead of silently writing to the global object.
Visual Diagrams
How was the regular function called?
|
+-- new Fn(...) -> this is the new object
|
+-- fn.call(obj, ...) -> this is obj
+-- fn.apply(obj, args) -> this is obj
+-- fn.bind(obj)(...) -> this is obj
|
+-- obj.fn(...) -> this is obj
|
+-- fn() -> default binding
strict: undefined
sloppy: global objectFor regular functions, the call site matters more than where the function was written.
Code Examples
Top-level this is environment-specific
Use this as context, not as a portable rule. Modern code should prefer globalThis when it truly needs the global object.
Strict mode makes default this fail loudly
A strict regular function called without an owner receives undefined as this.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function inspectDefault() {2 'use strict';3 if (this === undefined) {4 console.log('strict default');5 }6}7 8function inspectExplicit() {9 'use strict';10 console.log(this.label);11}12 13inspectDefault();14inspectExplicit.call({ label: 'explicit object' });Predict the output #2
1function Person(name) {2 this.name = name;3}4 5const ada = new Person('Ada');6console.log(ada.name);7console.log(ada instanceof Person);Coding Exercises
Classify a call site's this binding
EasyImplement classifyCallSite(expression) for the four expressions shown in the starter comments. Return default, implicit, explicit, or new. This is a reading exercise: focus on the syntax at the call site, not on where the function was defined.
Interview Questions
1What is `this` at the top level of JavaScript code?
It depends on the host and source type. In a classic browser script, top-level this is usually window. In an ES module, it is undefined. In Node CommonJS, the file is wrapped and top-level this is module.exports. For interviews, say that top-level this is environment-specific and then pivot to function-call binding rules.
Follow-ups
- How is top-level `this` different in an ES module?
- Why is `globalThis` safer when you need the global object?
2List the four `this` binding rules and their precedence.
The rules are default (fn()), implicit (obj.fn()), explicit (call, apply, bind), and new binding (new Fn()). Precedence is new > explicit > implicit > default. Strict mode affects only default binding: a plain call receives undefined instead of the global object.
Quiz
1. Which statement about top-level `this` is the safest interview answer?
2. Which binding rule has the highest precedence for regular functions?
Summary
- Top-level `this` is environment-specific; do not treat it as one portable rule.
- Regular function `this` is determined by the call site.
- The four rules are default, implicit, explicit, and `new` binding.
- Precedence is `new` > explicit > implicit > default.
- Strict mode changes default binding from global-object substitution to `undefined`.
Cheat Sheet
Top-level: classic script often global object; ES module undefined; Node CommonJS module.exports; workers vary.
Rules: fn() default, obj.fn() implicit, fn.call(obj) / apply / bind explicit, new Fn() new binding.
Precedence: new > explicit > implicit > default.
Strict mode: only default binding changes; plain-call this stays undefined.