In the world of JavaScript, the this keyword can be both a powerful ally and a tricky foe. How this is determined in different contexts is one of the most confusing concepts for developers. Luckily, JavaScript gives us a trio of "superheroes" to tame this: call(), apply(), and bind().

Mastering these three methods not only helps you solve complex this issues, but also opens up more flexible, efficient, and reusable ways to write code. Let’s dive deeper together! 🚀
The Problem: When "this" Goes Rogue
Before we get into details, let’s look at a classic example to see why we need call, apply, and bind.
const person = {
name: 'John Doe',
greet: function () {
console.log(`Hello, I am ${this.name}`)
},
}
const greetFunc = person.greet
greetFunc() // Result: "Hello, I am undefined"
Why undefined? Because when we assign person.greet to greetFunc and call it independently, this inside greetFunc no longer refers to the person object. Instead, it points to the global object (window in browsers) in non-strict mode, or is undefined in strict mode. This is where call, apply, and bind shine.
Call: Borrow a Method Directly
The call() method lets you invoke a function and explicitly set the value of this inside that function. You can also pass arguments individually, separated by commas.
Syntax
function.call(thisArg, arg1, arg2, ...);
thisArg: The value you wantthisto be inside the function.arg1, arg2, ...: Arguments passed to the function.
Practical Example
Let’s fix the original problem using call():
const person = {
name: 'John Doe',
greet: function () {
console.log(`Hello, I am ${this.name}`)
},
}
const anotherPerson = {
name: 'Jane Smith',
}
person.greet.call(anotherPerson) // Result: "Hello, I am Jane Smith"
Here, we "borrowed" the greet method from person and executed it in the context of anotherPerson. this inside greet is now set to anotherPerson, so this.name returns "Jane Smith".
Apply: Call’s Twin Brother
apply() works almost exactly like call(): it also executes a function with a specified this value. The only difference is how arguments are passed. Instead of passing arguments individually, apply() takes an array (or array-like object) of arguments.
Syntax
function.apply(thisArg, [argsArray]);
thisArg: Same ascall().[argsArray]: An array or array-like object containing arguments for the function.
Practical Example
Let’s look at a function that needs multiple arguments:
function introduce(profession, city) {
console.log(`I am ${this.name}, a ${profession} from ${city}.`)
}
const person = {
name: 'Peter Pan',
}
const details = ['software engineer', 'Neverland']
introduce.apply(person, details)
// Result: "I am Peter Pan, a software engineer from Neverland."
apply() is especially useful when you have an array of data and want to pass its elements as arguments to a function.
Bind: Create a Permanently "Bound" Copy
Unlike call() and apply(), which execute the function immediately, bind() does not call the function. Instead, it creates a new function with this permanently bound to the value you specify.
Syntax
function.bind(thisArg, arg1, arg2, ...);
thisArg: The value thatthiswill always refer to in the new function.arg1, arg2, ...: (Optional) Arguments to be partially applied.
Practical Example
bind() is the perfect solution for our original problem, especially in situations like event handling or callbacks.
const person = {
name: 'Alice Wonderland',
greet: function () {
console.log(`Hello, I am ${this.name}`)
},
}
const boundGreet = person.greet.bind(person)
boundGreet() // Result: "Hello, I am Alice Wonderland"
// Even in a callback, `this` stays correct
setTimeout(boundGreet, 1000) // After 1 second: "Hello, I am Alice Wonderland"
The boundGreet function is a new version of person.greet where this will always be person, no matter how or where it’s called.
Quick Comparison: Call, Apply, and Bind
A quick summary table of Call, Apply, and Bind by key criteria:
| Criteria | call() | apply() | bind() |
|---|---|---|---|
| Execution | Calls function immediately ✅ | Calls function immediately ✅ | Does not call, returns new function ❌ |
| Arguments | Individually (arg1, arg2, ...) | As an array ([arg1, arg2]) | Individually, can be partially applied |
| Return value | Return value of original function | Return value of original function | New function with bound this |
Memory tip:
- Call: Comma-separated arguments.
- Apply: Array of arguments.
- Bind: Bound function.
Conclusion: When to Use Which?
Common real-world scenarios for using call(), apply(), and bind() effectively:
-
Use
call()orapply()when you want to execute a function immediately with a differentthiscontext.- Method borrowing: Borrow methods from other objects, e.g., use
Array.prototype.slice.call(arguments)to convertargumentsto a real array. - Calling functions with dynamic argument arrays: Use
apply()to pass an array of values to functions likeMath.maxorMath.min. Example:Math.max.apply(null, [1, 5, 2, 9]).
- Method borrowing: Borrow methods from other objects, e.g., use
-
Use
bind()when you need a function to use later, but want to ensure itsthiscontext never changes.- Event listeners and callbacks: The most common case. When passing an object’s method as an event handler (e.g.,
element.addEventListener('click', myObject.myMethod)),thisis lost.bind()is the perfect fix:element.addEventListener('click', myObject.myMethod.bind(myObject)). - Partial application:
bind()lets you create new functions with some arguments preset.
function multiply(a, b) { return a * b } const double = multiply.bind(null, 2) // `this` is irrelevant, set to null console.log(double(5)) // Result: 10 (same as multiply(2, 5)) - Event listeners and callbacks: The most common case. When passing an object’s method as an event handler (e.g.,
In short, call(), apply(), and bind() are powerful tools in every JavaScript developer’s toolkit. They not only give you full control over the this keyword, but also encourage modular and reusable code. By understanding their subtle differences and ideal use cases, you can write cleaner, more predictable, and less error-prone code.
Next time you face a "lost" this, remember this powerful trio!
![[JS Basics] Conditional Statements in JavaScript: Examples & Effective Usage](/images/blog/conditional-statements-in-javascript.webp)
![[JS Basics] Loops in JavaScript: A Detailed Guide for Beginners](/images/blog/loops-in-javascript.webp)
![[Advanced JS] Data Structures & Algorithms: Practical Applications with JavaScript](/images/blog/data-structures-and-algorithms-with-javascript.webp)
![[JS Basics] Objects in JavaScript: Concepts & Effective Usage](/images/blog/objects-in-javascript.webp)