But first, what is this?
In JavaScript, this refers to the object that is currently calling the function. But the tricky part is — this changes depending on how the function is called, not where it is written.
const user = {
name: "Manish",
greet: function() {
console.log("Hello, " + this.name);
}
};
user.greet(); // "Hello, Manish" — this = user ✓
This works fine. But what happens when we take the function out of the object?
const greetFn = user.greet;
greetFn(); // "Hello, undefined" — this = window (or undefined in strict mode) ✗
The moment we store the method in a variable and call it separately, this is no longer pointing to user. It lost its context. This is the most common problem in JavaScript.
The problem: losing this
This happens in many real-world situations:
const user = {
name: "Manish",
greet: function() {
console.log("Hello, " + this.name);
}
};
// Problem 1: passing method as a callback
setTimeout(user.greet, 1000); // "Hello, undefined" ✗
// Problem 2: extracting method to a variable
const fn = user.greet;
fn(); // "Hello, undefined" ✗
// Problem 3: using in event handlers
button.addEventListener("click", user.greet); // this = button, not user ✗
In all these cases, we lose the original this context. This is exactly why call(), apply(), and bind() exist — they let us manually set what this should be.
bind()
Returns a new function
Does NOT call immediately
Use: save for later
call()
Calls immediately
Args: one by one
fn.call(obj, a, b)
apply()
Calls immediately
Args: as an array
fn.apply(obj, [a, b])
Bind
The bind() method creates a new function that, when called, has its this keyword set to the provided value. It does not call the function immediately — it returns a copy with this permanently fixed.
var pokemon = {
firstname: 'Pika',
lastname: 'Chu ',
getPokeName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var pokemonName = function() {
console.log(this.getPokeName() + 'I choose you!');
};
var logPokemon = pokemonName.bind(pokemon);
// creates new object and binds pokemon. 'this' of pokemon === pokemon now
logPokemon(); // 'Pika Chu I choose you!'
When we use the bind() method:
- The JS engine is creating a new
pokemonName instance and binding pokemon as its this variable. It is important to understand that it copies the pokemonName function.
- After creating a copy of the
pokemonName function it is able to call logPokemon(), although it wasn’t on the pokemon object initially. It will now recognize its properties (Pika and Chu) and its methods.
After we bind() a value we can use the function just like it was any other normal function.
When to use bind in real life
The most common use case is when passing object methods as callbacks:
const user = {
name: "Manish",
greet: function() {
console.log("Hello, " + this.name);
}
};
// Without bind — this is lost
setTimeout(user.greet, 1000); // "Hello, undefined" ✗
// With bind — this is permanently fixed
setTimeout(user.greet.bind(user), 1000); // "Hello, Manish" ✓
Call & Apply
The call() method calls a function immediately with a given this value and arguments provided individually. We can call any function, and explicitly specify what this should reference within the calling function.
The main differences between bind() and call():
- Accepts additional parameters as well
- Executes the function it was called upon right away.
- The
call() method does not make a copy of the function it is being called on.
call() and apply() serve the exact same purpose. The only difference is that call() expects all parameters to be passed in individually, whereas apply() expects an array of all parameters.
var pokemon = {
firstname: 'Pika',
lastname: 'Chu ',
getPokeName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var pokemonName = function(snack, hobby) {
console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};
pokemonName.call(pokemon, 'sushi', 'algorithms');
// Pika Chu loves sushi and algorithms
pokemonName.apply(pokemon, ['sushi', 'algorithms']);
// Pika Chu loves sushi and algorithms
When to use call/apply in real life
A common use case is borrowing methods from one object and using them on another:
const person1 = {
name: "Manish",
introduce: function(city, job) {
console.log(this.name + " from " + city + ", works as " + job);
}
};
const person2 = { name: "Rahul" };
// person2 doesn't have introduce(), but we can borrow it from person1
person1.introduce.call(person2, "Mumbai", "Developer");
// "Rahul from Mumbai, works as Developer"
Another classic use case is using Math.max with an array — Math.max does not accept an array, so we use apply:
const numbers = [5, 2, 9, 1, 7];
Math.max.apply(null, numbers); // 9
// In modern JS, we can also use spread operator
Math.max(...numbers); // 9
Quick summary
In simple language — all three methods let us control what this points to. Use bind() when we want to fix this for later use (callbacks, event handlers). Use call() or apply() when we want to borrow a method and run it immediately on a different object. The only difference between call and apply is how we pass arguments — one by one or as an array.