The Magic of this, call(), apply(), and bind() in JavaScript

What is this keyword -
In javascript most confusing topic to understanding this , how this keyword context changes when you use with call() , apply() & apply() . But don't worry i will try to my best break it down and simple and real example .
What is this in JavaScript ?
this = who is calling/running the function .
Real-World Analogy
Imagine in a recipe book . The recipe says "add salt to my pot". But whose pot ?
It depend on Who is using the recipe !
If Raghav uses it → my pot = Raghav's pot
If Shibu uses it → my pot = Shibu's pot
If no one specific uses it → my pot = nobody's pot
That's exactly how this work !
function greet() {
console.log("I am " + this);
}
greet(); // I am [object global]
Who called ? greet nobody specific → global object
let person = {
name: "Alice",
greet: function() {
console.log("I am " + this.name);
}
};
person.greet(); // Output: "I am Alice"
Who called greet ? person object --> this = person
let person1 = {
name: "Alice",
intro: function() {
console.log("Hello, I am " + this.name);
}
};
let person2 = {
name: "Bob"
};
person1.intro(); // Output: "Hello, I am Alice"
person2.intro = person1.intro;
person2.intro(); // Output: "Hello, I am Bob"
Who call intro first ? person1 --> this = person1
Then , In code person2.intro = person1.intro .
It means we just put intro function defination of person1 inside person2 in their key name intro .
now person2 :
{
name : "Bob",
intro : function() {
console.log("Hello, I am " + this.name);
}
}
Who call intro ? person2 --> this = person2 .
Same function , Different caller = Different this .
Important Rule: It's About WHO Called It, Not WHERE It's Defined
The location where you write the function , it doesn't matter. What matters is who calls/runs the function.
let teacher = {
name: "Mr. Smith",
teach: function() {
console.log(this.name + " is teaching");
}
};
let student = {
name: "John"
};
teacher.teach();
// Who teach ? teacher → Output: "Mr. Smith is teaching"
student.teach = teacher.teach;
student.teach();
// who teach ? student → Output: "John is teaching"
let func = teacher.teach;
// teach function defination assign to func
/*
console.log(`${func}`);
Output: function() {
console.log(this + " is teaching");
}
*/
func();
// Who call func? global object (global object has no name key so give undefined) → Output: "undefined is teaching"
The function not change. Only the caller changed. so
thischanged!
let animal = {
sound: "bark",
makeSound: function() {
console.log(this.sound);
}
};
let dog = { sound: "woof" };
dog.makeSound = animal.makeSound;
dog.makeSound(); // Output: "woof"
let cat = { sound: "meow" };
cat.makeSound = animal.makeSound;
cat.makeSound(); // Output: "meow"
let func = animal.makeSound;
func(); // Output: undefined
Summary:
When
dogcalls it →this= dogWhen
catcalls it →this= catWhen nobody calls it →
this= global object (global object not have sound key so this.sound --> undefined)
this Inside Arrow Functions
Arrow functions () => {} do not have their own this. Instead, they use this from their parent/outer scope.
Regular Function vs Arrow Function
let person = {
name: "Alice",
regularFunction: function() {
console.log("Regular: " + this.name);
},
arrowFunction: () => {
console.log("Arrow: " + this.name);
}
};
person.regularFunction(); // Output: "Regular: Alice"
person.arrowFunction(); // Output: "Arrow: undefined"
Why the difference? The arrow function doesn't have its own this. It looks outside the object for this, and outside there is no name property.
❗Arrow function rule: Looks for
thisin function scope, not object scope!
let user = {
username: "Bob",
greet: function() {
console.log("1. this in regular: " + this.username);
let arrow = () => {
console.log("2. this in arrow: " + this.username);
};
arrow();
}
};
user.greet();
// Output:
// "1. this in regular: Bob"
// "2. this in arrow: Bob"
Arrow function inside an regular function and regular function own this . So as per definition , arrow function it look for this in parent scope which is greet regular function ./q
Arrow function = "Borrow
thisfrom parent function"
Key Point: call(), apply(), bind() Don't Work with Arrow Functions
Arrow functions ignore call(), apply(), and bind() because they don't have their own this to control.
The Problem We Need to Solve
Now, what if we want to use a method from one object with another object?
let person1 = {
name: "Alice",
introduce: function() {
console.log("I am " + this.name);
}
};
let person2 = {
name: "Charlie"
};
let func = person1.introduce;
func(); //"I am undefined"
The problem: We lost the connection between the function and person1.
The solution: Use call(), apply(), and bind() to control this!
What call() Does
call() lets you borrow a method from one object and use it with another object immediately.
Syntax:
function.call(thisObject, argument1, argument2, ...);
Example 4: Using call()
let person1 = {
name: "Alice",
greet: function(greeting) {
console.log(greeting + ", my name is " + this.name);
}
};
let person2 = {
name: "Charlie"
};
// Borrow greet of person1 method for person2
person1.greet.call(person2, "Hello");
//"Hello, my name is Charlie"
What happened? We told the greet function: Run, but treat person2 as this.
call() with Multiple Arguments
let user = {
name: "Diana",
login: function(password, timestamp) {
console.log(this.name + " logged in with password and timestamp: " + timestamp);
}
};
let admin = {
name: "Eve"
};
user.login.call(admin, "secret123", "2024-03-05");
// "Eve logged in with password and timestamp: 2024-03-05"
What apply() Does
apply() works exactly like call(), but it takes arguments as array instead passing one by one.
Syntax:
function.apply(thisObject, [argument1, argument2, ...]);
Using apply()
let person = {
name: "Frank",
introduce: function(age, city) {
console.log(this.name + " is " + age + " years old and lives in " + city);
}
};
let person2 = {
name: "Grace"
};
person.introduce.apply(person2, [28, "New York"]);
//"Grace is 28 years old and lives in New York"
Practical Use of apply()
apply() is perfect when you have arguments in an array:
let calculator = {
add: function(a, b, c) {
return a + b + c;
}
};
let numbers = [5, 10, 15];
// apply() unpacks the array
let result = calculator.add.apply(null, numbers);
console.log(result); // Output: 30
What bind() Does
bind() creates a new function with this permanently attach to that obejct. Unlike call() and apply(), it doesn't run the function immediately.
Syntax:
let newFunction = function.bind(thisObject, argument1, argument2, ...);
Using bind()
let person = {
name: "Henry",
greet: function() {
console.log("Hello, I'm " + this.name);
}
};
let person2 = {
name: "Ivy"
};
let greetIvy = person.greet.bind(person2);
greetIvy(); //"Hello, I'm Ivy"
greet() method is permanently bound to person2 object, so this always = person2
bind() for Storing Functions
let player = {
name: "Jack",
health: 100,
takeDamage: function(damage) {
this.health -= damage;
console.log(this.name + " now has " + this.health + " health");
}
};
let jackTakeDamage = player.takeDamage.bind(player);
setTimeout(jackTakeDamage, 1000, 10);
// After 1 second: "Jack now has 90 health"
bind() permanently ties the takeDamage() function to the player object, so this = player forever, no matter when or where it's called.
Comparison Table - call() vs apply() vs bind() vs Arrow Functions
| Feature | Regular Function | Arrow Function | call() |
apply() |
bind() |
|---|---|---|---|---|---|
Has own this? |
Yes | No | Yes | Yes | Yes |
this from where? |
Caller/Object | Parent scope | Controlled | Controlled | Controlled |
| Runs immediately? | N/A | N/A | Yes | Yes | No |
| Arguments format | Any | Any | Separate | Array | Separate |
| Works with call/apply/bind? | ✅ Yes | ❌ No |
I hope this 😂 blog means my blog , help you to understand call(), apply() & bind() .
Happy Coding 👨💻!



