Call, Bind, and Apply in JavaScript
January 4, 2026
Call, Bind, and Apply in JavaScript
Overview
call, bind, and apply are methods available on all JavaScript functions. They allow you to control the value of this when a function is executed, and in the case of call and apply, immediately invoke the function.
The this Problem
In JavaScript, the value of this depends on how a function is called. Sometimes you need to explicitly set what this should refer to.
const person = {
name: "John",
greet: function() {
console.log(`Hello, I'm ${this.name}`);
}
};
const greetFunction = person.greet;
greetFunction(); // "Hello, I'm undefined" (this is window/global)
call()
Syntax
function.call(thisArg, arg1, arg2, ...)
Characteristics
- Immediately invokes the function
- Sets
thisto the first argument - Accepts arguments as comma-separated values
- Returns the result of the function call
Example
const obj1 = {
name: "Ashish",
age: 1,
};
const obj2 = {
name: "Akash",
age: 2,
};
function randomFunc(x, y) {
return `<div>
My name is ${this.name} and friend is ${x} and ${y}
</div>`;
}
// Using call
const callMethod = randomFunc.call(obj2, "aa", "Raahul");
console.log(callMethod);
// Output: "<div>My name is Akash and friend is aa and Raahul</div>"
More Examples
function introduce(greeting, punctuation) {
console.log(`${greeting}, I'm ${this.name}${punctuation}`);
}
const person1 = { name: "Alice" };
const person2 = { name: "Bob" };
introduce.call(person1, "Hello", "!"); // "Hello, I'm Alice!"
introduce.call(person2, "Hi", "."); // "Hi, I'm Bob."
apply()
Syntax
function.apply(thisArg, [argsArray])
Characteristics
- Immediately invokes the function
- Sets
thisto the first argument - Accepts arguments as an array
- Returns the result of the function call
- Useful when you have an array of arguments
Example
const obj1 = {
name: "Ashish",
age: 1,
};
function randomFunc(x, y) {
return `<div>
My name is ${this.name} and friend is ${x} and ${y}
</div>`;
}
// Using apply - arguments passed as array
const applyMethod = randomFunc.apply(obj1, ["Rahul", "Diya"]);
console.log(applyMethod);
// Output: "<div>My name is Ashish and friend is Rahul and Diya</div>"
Practical Use Case: Array Methods
// Finding max/min in array
const numbers = [5, 6, 2, 3, 7];
// Math.max doesn't accept arrays directly
const max = Math.max.apply(null, numbers); // 7
const min = Math.min.apply(null, numbers); // 2
// ES6 alternative (spread operator)
const maxES6 = Math.max(...numbers); // 7
Combining Arrays
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
// Using apply to push array2 into array1
array1.push.apply(array1, array2);
console.log(array1); // [1, 2, 3, 4, 5, 6]
// ES6 alternative
array1.push(...array2);
bind()
Syntax
function.bind(thisArg, arg1, arg2, ...)
Characteristics
- Does NOT invoke the function immediately
- Returns a new function with
thisbound to the first argument - Accepts arguments as comma-separated values
- Can be called later
- Useful for creating functions with preset
thisand arguments
Example
const obj1 = {
name: "Ashish",
age: 1,
};
function randomFunc(x, y) {
return `<div>
My name is ${this.name} and friend is ${x} and ${y}
</div>`;
}
// Using bind - returns a new function
const bindMethod = randomFunc.bind(obj1, "Amy", "Ayush");
console.log(bindMethod()); // Must call with () to execute
// Output: "<div>My name is Ashish and friend is Amy and Ayush</div>"
Practical Use Case: Event Handlers
class Button {
constructor(name) {
this.name = name;
this.clickCount = 0;
}
handleClick() {
this.clickCount++;
console.log(`${this.name} clicked ${this.clickCount} times`);
}
}
const button = new Button("Submit");
// Without bind - this would be undefined
document.getElementById('btn').addEventListener('click', button.handleClick);
// ❌ Error: Cannot read property 'clickCount' of undefined
// With bind - this is correctly set
document.getElementById('btn').addEventListener('click', button.handleClick.bind(button));
// ✅ Works correctly
Partial Application with bind()
function multiply(a, b, c) {
return a * b * c;
}
// Bind first argument
const multiplyBy2 = multiply.bind(null, 2);
console.log(multiplyBy2(3, 4)); // 24 (2 * 3 * 4)
// Bind first two arguments
const multiplyBy2And3 = multiply.bind(null, 2, 3);
console.log(multiplyBy2And3(4)); // 24 (2 * 3 * 4)
Comparison Table
| Method | Invokes Immediately? | Arguments Format | Returns | Use Case | |--------|---------------------|-----------------|---------|----------| | call | Yes | Comma-separated | Function result | When you know arguments and want immediate execution | | apply | Yes | Array | Function result | When you have arguments as array or unknown number | | bind | No | Comma-separated | New function | When you want to create a function for later use |
Side-by-Side Comparison
const person = {
name: "John",
age: 30
};
function introduce(greeting, punctuation) {
console.log(`${greeting}, I'm ${this.name}, age ${this.age}${punctuation}`);
}
// call - immediate execution, comma-separated args
introduce.call(person, "Hello", "!");
// Output: "Hello, I'm John, age 30!"
// apply - immediate execution, array args
introduce.apply(person, ["Hi", "."]);
// Output: "Hi, I'm John, age 30."
// bind - returns function, can call later
const boundIntroduce = introduce.bind(person, "Hey", "!");
boundIntroduce();
// Output: "Hey, I'm John, age 30!"
Common Patterns
1. Borrowing Methods
const person = {
firstName: "John",
lastName: "Doe",
getFullName: function() {
return `${this.firstName} ${this.lastName}`;
}
};
const person2 = {
firstName: "Jane",
lastName: "Smith"
};
// Borrow the method from person
const fullName = person.getFullName.call(person2);
console.log(fullName); // "Jane Smith"
2. Function Currying with bind()
function add(a, b, c) {
return a + b + c;
}
// Create curried versions
const add5 = add.bind(null, 5);
const add5And10 = add.bind(null, 5, 10);
console.log(add5(10, 15)); // 30 (5 + 10 + 15)
console.log(add5And10(15)); // 30 (5 + 10 + 15)
3. Setting Context in Callbacks
class Counter {
constructor() {
this.count = 0;
}
increment() {
this.count++;
console.log(this.count);
}
}
const counter = new Counter();
// Without bind
setTimeout(counter.increment, 1000); // ❌ this is undefined
// With bind
setTimeout(counter.increment.bind(counter), 1000); // ✅ Works
ES6 Arrow Functions Note
Arrow functions have lexical this - they don't have their own this and cannot be used with call, bind, or apply to change this.
const obj = {
name: "John",
regular: function() {
console.log(this.name); // "John"
},
arrow: () => {
console.log(this.name); // undefined (this is from outer scope)
}
};
obj.regular(); // "John"
obj.arrow(); // undefined
// call/bind/apply don't work with arrow functions
const boundArrow = obj.arrow.bind({ name: "Jane" });
boundArrow(); // Still undefined
Key Takeaways
- call() - Immediately invokes function with specified
thisand comma-separated arguments - apply() - Immediately invokes function with specified
thisand array of arguments - bind() - Returns new function with bound
thisand optional preset arguments - Use call/apply when you need immediate execution
- Use bind when you need to create a function for later use
- apply is useful when you have an array of arguments
- Arrow functions cannot use call/bind/apply to change
this