1. Introduction
The this keyword refers to the context in which a function executes — typically the object that is 'calling' the function. Unlike variables resolved through lexical scope, the value of this in a regular function is determined dynamically, at call time, based on how the function is invoked, not where it is defined. This makes this one of the trickiest concepts in JavaScript.
Cricket analogy: this is like which team a player represents on a given day — determined by who fields them at the toss, not by where they were born, so the same bowler's team context changes depending on how they're called up.
2. Syntax
const obj = {
name: "Maya",
greet() {
console.log(this.name);
},
};
obj.greet(); // implicit binding
const fn = obj.greet;
fn.call(obj); // explicit binding
fn.apply(obj);
const bound = fn.bind(obj);
bound();
function Person(name) {
this.name = name; // new binding
}
new Person("Ana");3. Explanation
There are four main rules for determining this in a regular function, in order of precedence: (1) new binding — when a function is called with new, this refers to the newly created object; (2) explicit binding — call(), apply(), or bind() set this to whatever object is passed as the first argument; (3) implicit binding — when a function is called as a method (obj.method()), this refers to the object before the dot; (4) default binding — when a function is called plainly (fn()), this is undefined in strict mode or the global object in non-strict mode.
Cricket analogy: The precedence is like: (1) being drafted new into a franchise sets your team outright, (2) being explicitly loaned to a specific XI overrides it, (3) playing as part of Mumbai's squad implicitly ties you to Mumbai, (4) an exhibition with no team assigned defaults to no side at all.
call() and apply() invoke a function immediately with a specified this (call takes arguments individually, apply takes them as an array), while bind() returns a new function permanently bound to the given this, to be called later. Arrow functions ignore all of these rules — they have no this of their own and always use the this from their enclosing lexical scope.
Cricket analogy: call() is like immediately sending a substitute fielder onto the pitch with instructions given one at a time, apply() is handing the same instructions as one written list, and bind() permanently assigns a twelfth man to a role for the tour — while an arrow-function fielder just follows whatever huddle surrounds them.
Gotcha: this is determined by HOW a function is called, not where it is defined. If you extract a method from an object and call it standalone (const fn = obj.method; fn();), it loses its implicit binding to obj and this becomes undefined (strict mode) or the global object — a very common source of bugs when passing object methods as callbacks.
4. Example
const person = {
name: "Maya",
greet() {
console.log(`Hi, I'm ${this.name}`);
},
};
person.greet(); // implicit binding
const greetFn = person.greet;
const boundGreet = greetFn.bind(person);
boundGreet(); // explicit binding via bind
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(`${this.name} makes a sound`);
};
const dog = new Animal("Rex"); // new binding
dog.speak();
const team = {
name: "Rockets",
members: ["Ana", "Leo"],
listMembers() {
this.members.forEach((member) => {
console.log(`${member} plays for ${this.name}`);
});
},
};
team.listMembers(); // arrow function inherits `this` from listMembers5. Output
Hi, I'm Maya
Hi, I'm Maya
Rex makes a sound
Ana plays for Rockets
Leo plays for Rockets6. Key Takeaways
- The value of this is determined by how a function is called, not where it is defined.
- Implicit binding: calling obj.method() sets this to obj.
- Explicit binding: call(), apply(), and bind() let you set this manually; bind() returns a new permanently-bound function.
- new binding: calling a function with new sets this to the newly created object.
- Arrow functions have no this of their own — they always inherit this lexically from their enclosing scope.
- Extracting a method from its object and calling it standalone loses implicit binding, often producing undefined.
Practice what you learned
1. What determines the value of this inside a regular (non-arrow) function?
2. What does greetFn.bind(person) return?
3. In the team.listMembers() example, why does the arrow function passed to forEach correctly log this.name as 'Rockets'?
4. What happens to this when a function is called using `new`?
5. If you write `const fn = obj.method; fn();`, what typically happens to this inside method?
Was this page helpful?
You May Also Like
Function Expressions and Arrow Functions
Compare function expressions and arrow functions, and understand how arrow functions handle this, arguments, and prototype differently.
Closures in JavaScript
Understand how closures let inner functions remember and access variables from their outer scope, and how loop variable capture can trip you up.
Classes in JavaScript
How ES6 class syntax provides a cleaner, structured way to create objects and implement object-oriented patterns on top of JavaScript's prototype system.
Prototypes and Prototypal Inheritance in JavaScript
The mechanism underlying every JavaScript object: how property lookups walk the prototype chain, and how `prototype`, `__proto__`, and `Object.getPrototypeOf` relate.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics