Explain the different ways the `this` keyword can be bound
TL;DR
The this keyword in JavaScript can be bound in several ways:
- Default binding: In non-strict mode,
thisrefers to the global object (windowin browsers). In strict mode,thisisundefined. - Implicit binding: When a function is called as a method of an object,
thisrefers to the object. - Explicit binding: Using
call,apply, orbindmethods to explicitly setthis. - New binding: When a function is used as a constructor with the
newkeyword,thisrefers to the newly created object. - Arrow functions: Arrow functions do not have their own
thisand inheritthisfrom the surrounding lexical context.
Binding precedence
For an ordinary function, stronger invocation forms take precedence over weaker defaults; arrows bypass this decision and capture this lexically.
A bound function is a special case: later call() or apply() calls cannot replace its stored receiver, although construction still takes precedence.
Default binding
In non-strict mode, if a function is called without any context, this refers to the global object (window in browsers). In strict mode, this is undefined.
function showThis() {console.log(this);}showThis(); // In non-strict mode: window, in strict mode: undefined
Implicit binding
When a function is called as a method of an object, this refers to the object.
const obj = {name: 'Alice',greet: function () {console.log(this.name);},};obj.greet(); // 'Alice'
Explicit binding
Using call, apply, or bind methods, you can explicitly set this.
Using call
function greet() {console.log(this.name);}const person = { name: 'Bob' };greet.call(person); // 'Bob'
Using apply
function greet(greeting) {console.log(greeting + ', ' + this.name);}const person = { name: 'Charlie' };greet.apply(person, ['Hello']); // 'Hello, Charlie'
Using bind
function greet() {console.log(this.name);}const person = { name: 'Dave' };const boundGreet = greet.bind(person);boundGreet(); // 'Dave'
New binding
When a function is used as a constructor with the new keyword, this refers to the newly created object.
function Person(name) {this.name = name;}const person = new Person('Eve');console.log(person.name); // 'Eve'
Arrow functions
Arrow functions do not have their own this and inherit this from the surrounding lexical context.
function makeGreeter() {return () => console.log(this.firstName);}const greet = makeGreeter.call({ firstName: 'Frank' });greet.call({ firstName: 'Grace' }); // 'Frank'; call() cannot rebind the arrow