Understanding call(), apply(), and bind() in JavaScript
JavaScript is a versatile language with powerful features that can sometimes be confusing, especially for newcomers. Three such features are call(), apply(), and bind(). These methods are used to control the context (this value) of a function, which is essential for writing flexible and maintainable code.
What is this in JavaScript?
Before diving into call(), apply(), and bind(), it's crucial to understand what this refers to in JavaScript. The value of this is determined by how a function is called. It can refer to different objects depending on the call context:
- In a method, thisrefers to the owner object.
- Alone, thisrefers to the global object (in non-strict mode) orundefined(in strict mode).
- In a function, thisrefers to the global object (in non-strict mode) orundefined(in strict mode).
- In an event, thisrefers to the element that received the event.
- thiscan be explicitly set using- call(),- apply(), or- bind().
For more on this topic, check out my other article on Understanding this in JavaScript
The call() Method
The call() method calls a function with a given this value and arguments provided individually. It allows for method borrowing, enabling one object to use a method from another object.
Syntax
function.call(thisArg, arg1, arg2, ...)
- thisArg: The value to use as- thiswhen calling the function.
- arg1, arg2, ...: Arguments for the function.
Example
const person = {
  firstName: 'John',
  lastName: 'Doe',
  fullName: function () {
    return `${this.firstName} ${this.lastName}`
  },
}
const anotherPerson = {
  firstName: 'Jane',
  lastName: 'Smith',
}
console.log(person.fullName.call(anotherPerson)) // Jane Smith
In this example, we borrowed the fullName method from the person object and called it on anotherPerson using call(). The this value inside fullName refers to anotherPerson.
The apply() Method
The apply() method is similar to call(), but it accepts arguments as an array or an array-like object. This is useful when you have an array of arguments and want to pass them to a function.
Syntax
function.apply(thisArg, [argsArray])
- thisArg: The value to use as- thiswhen calling the function.
- [argsArray]: An array or array-like object containing the arguments.
Example
const numbers = [1, 2, 3, 4, 5]
function sum(a, b, c, d, e) {
  return a + b + c + d + e
}
console.log(sum.apply(null, numbers)) // 15
In this example, we used apply() to pass the elements of the numbers array as arguments to the sum function.
The bind() Method
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. Unlike call() and apply(), bind() does not immediately call the function; it returns a new function.
Syntax
const boundFunction = function.bind(thisArg, arg1, arg2, ...)
- thisArg: The value to use as- thiswhen calling the new function.
- arg1, arg2, ...: Arguments to prepend to arguments provided to the bound function.
Example
const module = {
  x: 42,
  getX: function () {
    return this.x
  },
}
const retrieveX = module.getX
console.log(retrieveX()) // undefined
const boundGetX = retrieveX.bind(module)
console.log(boundGetX()) // 42
In this example, we used bind() to create a new function boundGetX with this set to module. When boundGetX is called, it correctly returns the value of module.x.
Differences Between call(), apply(), and bind()
While call(), apply(), and bind() are used to set the this value of a function, they have distinct differences:
- Immediate Invocation: call()andapply()invoke the function immediately, whilebind()returns a new function that can be invoked later.
- Arguments: call()accepts arguments individually, whereasapply()accepts arguments as an array.bind()allows partial application, where you can set some arguments initially and provide the rest later.
Summary Table
| Method | Invocation | Arguments | 
|---|---|---|
| call() | Immediate | Individually | 
| apply() | Immediate | As an array | 
| bind() | Later | Individually or partially | 
Use Cases
Understanding when to use each method is crucial for effective JavaScript programming:
- Method Borrowing: Use call()orapply()to borrow methods from other objects.
- Passing Arguments as Arrays: Use apply()when you have an array of arguments.
- Function Binding: Use bind()to create a new function with a specificthisvalue, useful for event handlers and callbacks.
Method Borrowing Example
const car = {
  brand: 'Toyota',
  getBrand: function () {
    return this.brand
  },
}
const bike = {
  brand: 'Yamaha',
}
console.log(car.getBrand.call(bike)) // Yamaha
Passing Arguments as Arrays Example
function greet(greeting, name) {
  return `${greeting}, ${name}!`
}
const args = ['Hello', 'Alice']
console.log(greet.apply(null, args)) // Hello, Alice!
Function Binding Example
const user = {
  name: 'Alice',
  greet: function (greeting) {
    console.log(`${greeting}, ${this.name}`)
  },
}
const greetUser = user.greet.bind(user)
greetUser('Hi') // Hi, Alice
Conclusion
In JavaScript, controlling the context (this value) of a function is essential for writing flexible and maintainable code. The call(), apply(), and bind() methods provide powerful ways to manipulate this and pass arguments to functions. By understanding their differences and use cases, you can leverage these methods to write more effective JavaScript code.
