The Magic of this, call(), apply(), and bind() in JavaScript
Introduction
Imagine you are in a chai shop in Delhi. The shop owner has a recipe for making chai. When you ask for chai, the owner makes it using their equipment and ingredients. The "chai shop owner" is the context, and "you" are the one requesting it. In JavaScript, this works the same way. It refers to the object that is calling the function.
In this blog, we will learn what this means, and three powerful methods (call(), apply(), and bind()) that let you control which object this refers to.
1. What this Means in JavaScript (Simple Explanation)
this refers to the object that is calling the function.
Think of this as an answer to the question: "Who is calling me?"
Simple Real-Life Analogy
Imagine you are a teacher, and you say "I will teach my class today."
If you are teaching at School A, "I" means "the teacher at School A"
If you are teaching at School B, "I" means "the teacher at School B"
The same person (you), but the meaning of "I" changes based on the context. Similarly, this changes based on who is calling the function.
Simple Code Example
const person = {
name: "Ashish",
greet: function() {
console.log("Hello, my name is " + this.name);
}
};
person.greet(); // Output: Hello, my name is Ashish
In this example, person is calling the greet function. So this refers to person, and this.name is "Ashish".
Global Context
When no object calls the function, this refers to the global object (in browsers, it is window):
function sayName() {
console.log(this);
}
sayName(); // this refers to global object (window in browsers)
2. this Inside Normal Functions
When a function is called directly (not as part of an object), this refers to the global object.
Example 1: Function Without an Object
function introduce() {
console.log("My name is " + this.name);
}
introduce(); // this refers to global object, this.name is undefined
In strict mode, this would be undefined:
"use strict";
function introduce() {
console.log(this); // undefined in strict mode
}
introduce();
Example 2: Variable in Global Scope
let globalName = "World";
function greet() {
console.log("Hello, " + this.name); // Tries to access global.name
}
greet(); // Output: Hello, undefined
The function cannot access variables directly through this in the global scope.
Key Point
In normal functions, this is determined by how the function is called, not where it is defined.
let person = {
name: "Ashish"
};
function getName() {
return this.name;
}
// Called as a normal function
console.log(getName()); // Output: undefined (this is global)
// Called through the person object
console.log(person.getName = getName); // We will assign it next
3. this Inside Objects
When a function is called as a method of an object (using dot notation), this refers to that object.
Example 1: Simple Object with Method
JavaScript
const student = {
name: "Ashish",
age: 20,
greet: function() {
console.log("Hello, I am " + this.name);
}
};
student.greet(); // Output: Hello, I am Ashish
Here, student calls the greet function, so this refers to student.
Example 2: Accessing Multiple Properties
JavaScript
const college = {
name: "IIIT Bangalore",
founded: 2009,
getInfo: function() {
return this.name + " was founded in " + this.founded;
}
};
console.log(college.getInfo());
// Output: IIIT Bangalore was founded in 2009
Example 3: Modifying Object Properties with this
JavaScript
const bank = {
accountBalance: 10000,
deposit: function(amount) {
this.accountBalance += amount;
console.log("New balance: " + this.accountBalance);
},
withdraw: function(amount) {
this.accountBalance -= amount;
console.log("New balance: " + this.accountBalance);
}
};
bank.deposit(5000); // Output: New balance: 15000
bank.withdraw(2000); // Output: New balance: 13000
Important: this is Dynamic
The value of this depends on how the function is called, not where it is defined:
const person1 = {
name: "Ashish",
greet: function() {
console.log("Hello, I am " + this.name);
}
};
const person2 = {
name: "Priya"
};
// Calling through person1
person1.greet(); // Output: Hello, I am Ashish
// Calling through person2
person2.greet = person1.greet;
person2.greet(); // Output: Hello, I am Priya (this refers to person2 now!)
Even though we are using the same function, this changes based on which object calls it!
4. What call() Does
The call() method lets you call a function and specify what this should refer to. It executes the function immediately.
Syntax
functionName.call(objectToUseAsThis, arg1, arg2, ...);
Example 1: Using call() to Set this
function introduce() {
console.log("My name is " + this.name);
}
const ashish = { name: "Ashish" };
const priya = { name: "Priya" };
// Call the function with ashish as this
introduce.call(ashish); // Output: My name is Ashish
// Call the function with priya as this
introduce.call(priya); // Output: My name is Priya
Without call(), we could not reuse this function for different objects. With call(), we can!
Example 2: call() with Arguments
function calculateAge(currentYear) {
return currentYear - this.birthYear;
}
const ashish = { birthYear: 2005 };
const priya = { birthYear: 2004 };
let ashishAge = calculateAge.call(ashish, 2026); // Output: 21
let priyaAge = calculateAge.call(priya, 2026); // Output: 22
console.log(ashishAge); // Output: 21
console.log(priyaAge); // Output: 22
Arguments after the object are passed to the function.
Example 3: College Enrollment
function enrollStudent(semester, course) {
console.log(this.name + " enrolled in " + course + " in semester " + semester);
}
const student1 = { name: "Ashish" };
const student2 = { name: "Priya" };
enrollStudent.call(student1, 4, "Data Structures");
// Output: Ashish enrolled in Data Structures in semester 4
enrollStudent.call(student2, 3, "Web Development");
// Output: Priya enrolled in Web Development in semester 3
Example 4: Borrowing Methods from Objects
const person = {
name: "Ashish",
greet: function(greeting) {
console.log(greeting + ", " + this.name);
}
};
const pet = {
name: "Buddy"
};
// Borrow the greet method from person for pet
person.greet.call(pet, "Woof"); // Output: Woof, Buddy
Even though pet does not have a greet method, we can use the one from person!
5. What apply() Does
The apply() method is similar to call(), but instead of listing arguments one by one, you pass them as an array.
Syntax
functionName.apply(objectToUseAsThis, [arg1, arg2, ...]);
Example 1: Using apply()
function introduce(greeting, punctuation) {
console.log(greeting + ", my name is " + this.name + punctuation);
}
const ashish = { name: "Ashish" };
// Using call (arguments one by one)
introduce.call(ashish, "Hello", "!");
// Output: Hello, my name is Ashish!
// Using apply (arguments in an array)
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, my name is Ashish!
Both produce the same result. The difference is how you pass arguments.
Example 2: Finding Maximum with apply()
A common use of apply() is to pass array elements as arguments:
const numbers = [10, 20, 50, 30, 5];
// Math.max expects individual arguments, not an array
// Without apply, this would not work:
// console.log(Math.max(numbers)); // Output: NaN
// With apply, we convert the array to individual arguments:
let max = Math.max.apply(null, numbers);
console.log(max); // Output: 50
Example 3: Adding Multiple Numbers
function addNumbers(a, b, c, d) {
return a + b + c + d;
}
const numbers = [10, 20, 30, 40];
let sum = addNumbers.apply(null, numbers);
console.log(sum); // Output: 100
Important: The First Argument (null or object)
When the object does not matter (or there is no specific object to use), pass null:
function add(a, b) {
return a + b;
}
let result = add.apply(null, [5, 10]); // null means "no specific object"
console.log(result); // Output: 15
6. What bind() Does
The bind() method creates a new function with a fixed this value. Unlike call() and apply(), bind() does NOT execute the function immediately. It returns a new function that you can call later.
Syntax
const newFunction = functionName.bind(objectToUseAsThis, arg1, arg2, ...);
Example 1: Using bind()
function greet(greeting) {
console.log(greeting + ", " + this.name);
}
const ashish = { name: "Ashish" };
// Create a new function with ashish as this
const ashishGreet = greet.bind(ashish);
// Call it later
ashishGreet("Hello"); // Output: Hello, Ashish
ashishGreet("Hi"); // Output: Hi, Ashish
Notice that we create the function first with bind(), then call it later. This is different from call() and apply(), which execute immediately.
Example 2: bind() with Preset Arguments
You can also preset some arguments:
function calculateFee(baseFee, discountPercentage) {
let discount = baseFee * (discountPercentage / 100);
return baseFee - discount;
}
const student = { name: "Ashish" };
// Create a function with preset discount of 10%
const calculateStudentFee = calculateFee.bind(null, 50000, 10);
let fee = calculateStudentFee();
console.log(fee); // Output: 45000
Example 3: bind() in Event Handlers
A common use of bind() is in event handlers:
const person = {
name: "Ashish",
clickHandler: function() {
console.log("Button clicked by " + this.name);
}
};
// Without bind, this would refer to the button element
// With bind, this refers to person
const button = document.querySelector("button");
button.addEventListener("click", person.clickHandler.bind(person));
(This is more advanced, but shows a real-world use case.)
Example 4: bind() for Later Execution
JavaScript
function greetStudent(greeting, subject) {
console.log(greeting + " " + this.name + ", you are learning " + subject);
}
const ashish = { name: "Ashish" };
const priya = { name: "Priya" };
// Create bound functions
const greetAshish = greetStudent.bind(ashish);
const greetPriya = greetStudent.bind(priya);
// Use them later
greetAshish("Welcome", "JavaScript"); // Output: Welcome Ashish, you are learning JavaScript
greetPriya("Hi", "Python"); // Output: Hi Priya, you are learning Python
7. Difference Between call(), apply(), and bind()
Now let's compare these three powerful methods.
Quick Comparison
| Method | Executes Immediately | Arguments | Returns |
|---|---|---|---|
| call() | Yes | One by one: arg1, arg2 |
Function result |
| apply() | Yes | As array: [arg1, arg2] |
Function result |
| bind() | No | One by one: arg1, arg2 |
New function (not executed) |
Side-by-Side Examples
call() Example
function introduce(greeting, punctuation) {
console.log(greeting + ", " + this.name + punctuation);
}
const ashish = { name: "Ashish" };
// call executes immediately with arguments one by one
introduce.call(ashish, "Hello", "!");
// Output: Hello, Ashish! (executed immediately)
apply() Example
function introduce(greeting, punctuation) {
console.log(greeting + ", " + this.name + punctuation);
}
const ashish = { name: "Ashish" };
// apply executes immediately with arguments as array
introduce.apply(ashish, ["Hello", "!"]);
// Output: Hello, Ashish! (executed immediately)
bind() Example
function introduce(greeting, punctuation) {
console.log(greeting + ", " + this.name + punctuation);
}
const ashish = { name: "Ashish" };
// bind creates a new function (not executed yet)
const ashishIntroduce = introduce.bind(ashish, "Hello", "!");
// Call it later
ashishIntroduce();
// Output: Hello, Ashish! (executed when we call it)
When to Use Each
Use call() When
You want to execute a function immediately with a specific this and arguments one by one:
function sayHello(greeting) {
console.log(greeting + ", " + this.name);
}
const person = { name: "Ashish" };
sayHello.call(person, "Hello"); // Execute now
Use apply() When
You want to execute a function immediately with a specific this but have arguments in an array:
function sum(a, b, c) {
return a + b + c;
}
const numbers = [10, 20, 30];
let result = sum.apply(null, numbers); // Execute now with array
Use bind() When
You want to create a new function to use later:
function calculateAge(year) {
return 2026 - this.birthYear - year;
}
const person = { birthYear: 2005 };
// Create for later use
const getPersonAge = calculateAge.bind(person, 5);
// Use it later
console.log(getPersonAge()); // Output: 16
Detailed Comparison Table
| Aspect | call() | apply() | bind() |
|---|---|---|---|
| Executes immediately | Yes | Yes | No |
| Returns | Function result | Function result | New function |
| Arguments format | One by one: arg1, arg2 |
Array: [arg1, arg2] |
One by one: arg1, arg2 |
| First parameter | Object for this |
Object for this |
Object for this |
| Use case | Quick execution | Array arguments | Store for later |
| Example | fn.call(obj, 1, 2) |
fn.apply(obj, [1, 2]) |
fn.bind(obj, 1, 2) |
Visual Representation
How call() Works
Function Definition
|
v
sayHi()
|
+------ call(person1) ------> Execute with person1 as this
|
+------ call(person2) ------> Execute with person2 as this
Result: Function executes immediately with specified this
How apply() Works
Function Definition
|
v
addNumbers()
|
+------ apply(null, [10, 20]) ------> Execute with array as arguments
Result: Function executes immediately, array unpacked to arguments
How bind() Works
Function Definition
|
v
greet()
|
+------ bind(ashish, "Hello") ------> Create NEW function
|
v
boundGreet
|
+------ Call later when needed ------> Execute
Result: New function created, not executed until called
Summary
thisrefers to the object that is calling the functionIn normal functions,
thisis the global objectIn object methods,
thisrefers to that object
call()executes a function immediately with a specificthisand arguments one by oneSyntax:
fn.call(object, arg1, arg2)Use when you need immediate execution
apply()executes a function immediately with a specificthisand arguments as an arraySyntax:
fn.apply(object, [arg1, arg2])Use when arguments are in an array
bind()creates a new function with a fixedthisvalue for later useSyntax:
fn.bind(object, arg1, arg2)Use when you need to store a function for later
Key differences:
call()andapply()execute immediatelybind()creates a new functioncall()andbind()use arguments one by oneapply()uses arguments as an array
Real-world uses:
Borrowing methods from other objects
Creating specialized versions of functions
Using in event handlers and callbacks
Working with array methods like
Math.max()




