JavaScript this Binding in Standard Function Calls
In JavaScript, the value of the this keyword inside
standard functions is determined dynamically at runtime based on how and
where the function is executed, rather than where it is defined.
Understanding this binding comes down to evaluating the
execution context through four primary rules: default binding, implicit
binding, explicit binding, and constructor binding. This guide breaks
down each mechanism to clarify how standard function calls assign their
execution context.
1. Default Binding (Standalone Function Calls)
When a standard function is invoked on its own without any qualifying context, JavaScript uses default binding.
- Non-Strict Mode:
thisdefaults to the global execution context—thewindowobject in web browsers or theglobalobject in Node.js environments. - Strict Mode (
'use strict'):thisremainsundefinedto prevent accidental modifications to the global object.
function showContext() {
console.log(this);
}
showContext(); // Logs: window (in browsers) / global (in Node)
function showStrictContext() {
'use strict';
console.log(this);
}
showStrictContext(); // Logs: undefined2. Implicit Binding (Method Invocations)
When a function is invoked as a method belonging to an object (using
dot notation or bracket notation), this implicitly binds to
the immediate object containing the call site.
const user = {
name: 'Alex',
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
user.greet(); // Logs: "Hello, my name is Alex"If multiple nested objects are chained together, this
binds to the object directly preceding the method invocation:
const company = {
department: {
name: 'Engineering',
getName() {
return this.name;
}
}
};
console.log(company.department.getName()); // Logs: "Engineering"The Pitfall of Losing Implicit Context
Assigning an object method to a standard variable or passing it as a callback isolates the function from its parent object. When executed, it falls back to default binding:
const standaloneGreet = user.greet;
standaloneGreet(); // Logs: "Hello, my name is undefined" (or errors in strict mode)3. Explicit Binding
(call, apply, and bind)
JavaScript provides built-in prototype methods that allow you to
explicitly dictate what this should reference during
execution.
Function.prototype.call(thisArg, arg1, arg2, ...): Invokes the function immediately, bindingthistothisArgand passing additional arguments individually.Function.prototype.apply(thisArg, [argsArray]): Invokes the function immediately, bindingthistothisArgand accepting additional arguments as an array.Function.prototype.bind(thisArg, arg1, ...): Does not invoke the function immediately. Instead, it returns a new function with itsthispermanently locked tothisArg.
function introduce(greeting, punctuation) {
console.log(`${greeting}, I am ${this.name}${punctuation}`);
}
const person = { name: 'Sarah' };
// Using call and apply
introduce.call(person, 'Hello', '.'); // Logs: "Hello, I am Sarah."
introduce.apply(person, ['Hi', '!']); // Logs: "Hi, I am Sarah!"
// Using bind
const boundIntroduce = introduce.bind(person, 'Greetings');
boundIntroduce('?'); // Logs: "Greetings, I am Sarah?"4. Constructor Binding
(new Operator)
When a standard function is invoked with the new keyword
as a constructor, a series of steps occur automatically:
- A new, empty object is created.
- The newly created object’s prototype is linked to the function’s
prototypeproperty. - The function executes with
thisbound directly to the new object. - The function returns the newly created object (unless an alternate object is explicitly returned).
function Car(make, model) {
this.make = make;
this.model = model;
}
const myCar = new Car('Toyota', 'Corolla');
console.log(myCar.make); // Logs: "Toyota"Order of Precedence
When multiple rules appear to conflict, JavaScript resolves
this using a strict hierarchy of precedence:
newKeyword:thisrefers to the newly instantiated object.- Explicit Binding (
bind,call,apply):thisrefers to the explicitly provided object. - Implicit Binding (Object Methods):
thisrefers to the context object before the dot. - Default Binding:
thisrefers to the global object orundefinedin strict mode.