In JavaScript, the this keyword refers to a value determined by how a function is called. Sometimes, you may want to control which object a function uses as its this value.
JavaScript provides three methods for controlling this in regular functions: call(), apply(), and bind().
These methods are useful when you want to reuse functions with different objects, pass arguments in different ways, or create a function that remembers a specific this value.
In this tutorial, you will learn how call(), apply(), and bind() work, how they differ, and when to use each method.
What Are call(), apply(), and bind() in JavaScript?
The call(), apply(), and bind() methods are available on functions and allow you to specify the this value for a regular function.
Although all three can control this, they work differently.
| Method | Purpose | How arguments are passed | Executes immediately? |
|---|---|---|---|
call() | Invokes a function with a specified this value | Individually | Yes |
apply() | Invokes a function with a specified this value | As an array or array-like object | Yes |
bind() | Creates a new function with a specified this value | Individually, optionally in advance | No |
For example, suppose two objects have different names, but you want to use the same function to display both names. You can reuse the function with call(), apply(), or bind() instead of writing a separate function for each object.
JavaScript call() Method
The call() method invokes a function immediately with a specified this value. You can pass the function’s arguments individually after the first argument.
Syntax of call()
functionName.call(thisValue, arg1, arg2, ...);
Here is what each argument means:
functionName: The function you want to execute.thisValue: The value to use asthisinside the function.arg1,arg2: The arguments passed to the function.
Example of call()
const person = {
name: "Karim"
};
function greet() {
console.log("Hello, " + this.name);
}
greet.call(person);
Output:
Hello, Karim
In this example, call(person) invokes greet() immediately and sets its this value to the person object.
Therefore, this.name accesses the value "Karim".
Passing Arguments Using call()
You can also pass arguments individually using call().
const person = {
name: "Karim"
};
function introduce(city, country) {
console.log(
this.name + " lives in " + city + ", " + country
);
}
introduce.call(person, "Hyderabad", "India");
Output:
Karim lives in Hyderabad, India
The first argument, person, becomes the function’s this value. The remaining arguments, "Hyderabad" and "India", are passed to introduce() as its parameters.
Reusing a Function with Different Objects
One advantage of call() is that you can use the same function with different objects.
const person1 = {
name: "Karim"
};
const person2 = {
name: "Ahmed"
};
function greet() {
console.log("Hello, " + this.name);
}
greet.call(person1);
greet.call(person2);
Output:
Hello, Karim
Hello, Ahmed
The function remains the same, but the this value changes with each call.
JavaScript apply() Method
The apply() method works similarly to call(). It invokes a function immediately with a specified this value, but it accepts the function’s arguments as an array or array-like object.
Syntax of apply()
functionName.apply(thisValue, [arg1, arg2, ...]);
The first argument specifies the this value. The second argument contains the function’s arguments.
Example of apply()
const person = {
name: "Karim"
};
function introduce(city, country) {
console.log(
this.name + " lives in " + city + ", " + country
);
}
introduce.apply(person, ["Hyderabad", "India"]);
Output:
Karim lives in Hyderabad, India
Here, apply() sets this to person and passes the array elements as individual arguments to introduce().
Passing an Array of Arguments
The apply() method is particularly useful when your arguments are already stored in an array.
function calculate(a, b, c) {
return a + b + c;
}
const numbers = [10, 20, 30];
const result = calculate.apply(null, numbers);
console.log(result);
Output:
60
The numbers array supplies the three arguments to calculate().
In this example, the function does not use this, so null is passed for the this argument. When a regular function is called with null or undefined as its this value, strict mode preserves that value, while non-strict mode substitutes the global object. Since calculate() does not reference this, the result is 60 in either case.
For modern JavaScript, the spread operator is often a convenient alternative:
function calculate(a, b, c) {
return a + b + c;
}
const numbers = [10, 20, 30];
console.log(calculate(...numbers));
Output:
60
Learn more about the JavaScript spread operator to understand how array elements can be passed as individual function arguments.
JavaScript bind() Method
The bind() method creates a new function with a specified this value. Unlike call() and apply(), it does not execute the function immediately.
Instead, you can store the returned function in a variable and call it later.
Syntax of bind()
const newFunction = functionName.bind(thisValue, arg1, arg2, ...);
Here, thisValue specifies the this value for the new function. Additional arguments can optionally be supplied in advance.
Example of bind()
const person = {
name: "Karim"
};
function greet() {
console.log("Hello, " + this.name);
}
const boundGreet = greet.bind(person);
boundGreet();
Output:
Hello, Karim
The expression greet.bind(person) creates a new function whose this value is bound to person.
The function executes only when boundGreet() is called.
Passing Arguments Using bind()
You can provide arguments when creating the bound function or when calling it later.
const person = {
name: "Karim"
};
function introduce(city, country) {
console.log(
this.name + " lives in " + city + ", " + country
);
}
const boundIntroduce = introduce.bind(person, "Hyderabad");
boundIntroduce("India");
Output:
Karim lives in Hyderabad, India
Here, "Hyderabad" is supplied when the function is bound. The remaining argument, "India", is supplied when the new function is called.
This technique is called partial application because some of the function’s arguments are provided in advance.
Using bind() with setTimeout()
The bind() method is useful when a callback needs a specific this value.
const person = {
name: "Karim",
greet() {
console.log("Hello, " + this.name);
}
};
setTimeout(person.greet.bind(person), 1000);
Output after approximately one second:
Hello, Karim
Without bind(person), the method would be passed as a standalone callback, losing its original receiver. Binding creates a function that retains person as its this value when invoked normally.
Arrow functions are another option when you want a callback to inherit this from its surrounding lexical context.
Difference Between call(), apply(), and bind()
All three methods can specify this for regular functions, but the main difference is how they invoke the function and pass arguments.
Consider this example:
const person = {
name: "Karim"
};
function greet(message, punctuation) {
console.log(message + ", " + this.name + punctuation);
}
greet.call(person, "Hello", "!");
greet.apply(person, ["Welcome", "!"]);
const boundGreet = greet.bind(person, "Good morning");
boundGreet(".");
Output:
Hello, Karim!
Welcome, Karim!
Good morning, Karim.
The first call uses call() with individual arguments. The second uses apply() with an array. The third creates a bound function using bind() and executes it later.
| Feature | call() | apply() | bind() |
|---|---|---|---|
Sets this for a regular function | Yes | Yes | Yes, for the returned function |
| Executes the original function immediately | Yes | Yes | No |
| Returns the function’s result | Yes | Yes | Returns a new function |
| Argument format | Individual arguments | Array or array-like object | Optional preset arguments |
| Best used when | Calling now with individual arguments | Calling now with arguments in an array | Calling later with a fixed this value |
Important Rules About call(), apply(), and bind()
They Do Not Override Arrow Function this
Arrow functions inherit this from their surrounding lexical context. Calling an arrow function with call() or apply(), or creating a bound arrow function with bind(), does not change that lexical this value.
const person = {
name: "Karim"
};
const greet = () => {
console.log(this);
};
greet.call(person);
The arrow function does not use person as its this value. It uses the this value from the surrounding scope.
bind() Does Not Change the Original Function
The bind() method returns a new function. It does not modify the original function’s this behavior.
const person = {
name: "Karim"
};
function greet() {
console.log("Hello, " + this.name);
}
const boundGreet = greet.bind(person);
boundGreet();
Output:
Hello, Karim
The new function uses person as its bound this value, while the original greet function remains unchanged.
A Bound this Value Cannot Normally Be Replaced
For an ordinary bound function, calling it with another this value through call() or apply() does not replace the value already bound by bind().
const person1 = {
name: "Karim"
};
const person2 = {
name: "Ahmed"
};
function greet() {
console.log(this.name);
}
const boundGreet = greet.bind(person1);
boundGreet.call(person2);
Output:
Karim
The bound function continues to use person1 as its this value. The person2 argument does not replace it.
Frequently Asked Questions
What is the difference between call() and apply()?
Both methods invoke a function immediately with a specified this value. The difference is how arguments are passed: call() accepts individual arguments, while apply() accepts an array or array-like object.
What is the difference between apply() and bind()?
apply() invokes a function immediately, while bind() returns a new function that can be executed later with a bound this value.
Does bind() execute a function immediately?
No. bind() creates and returns a new function. That function executes only when it is called.
Can I use call(), apply(), and bind() with arrow functions?
You can invoke arrow functions using call() or apply() and create a bound wrapper using bind(). However, these methods cannot change an arrow function’s lexical this value.
Which method should I use?
Use call() when you want to invoke a function immediately with individual arguments. Use apply() when the arguments are already in an array or array-like object. Use bind() when you need a new function with a fixed this value for later execution.
Are call(), apply(), and bind() available on all functions?
They are available through Function.prototype and can generally be used with regular JavaScript functions. Their effect on this differs for arrow functions because arrow functions have lexical this.
Conclusion
The call(), apply(), and bind() methods help you control how regular JavaScript functions use this.
call()invokes a function immediately with individual arguments.apply()invokes a function immediately with arguments supplied as an array or array-like object.bind()creates a new function with a specifiedthisvalue for later execution.
Understanding these methods helps you reuse functions, handle callbacks, and avoid common problems involving the this keyword in JavaScript.