109 lines
2.9 KiB
Plaintext
109 lines
2.9 KiB
Plaintext
---
|
|
title: What's the difference between `.call` and `.apply`?
|
|
---
|
|
|
|
## TL;DR
|
|
|
|
`.call` and `.apply` are used to invoke functions with a specific this context and arguments. The primary difference lies in how they accept arguments:
|
|
|
|
- `.call(thisArg, arg1, arg2, ...)`: Takes arguments individually.
|
|
- `.apply(thisArg, [argsArray])`: Takes arguments as an array.
|
|
|
|
---
|
|
|
|
Both `.call` and `.apply` are used to invoke functions and the first parameter will be used as the value of `this` within the function. However, `.call` takes in comma-separated arguments as the next arguments while `.apply` takes in an array of arguments as the next argument. An easy way to remember this is C for `call` and comma-separated and A for `apply` and an array of arguments.
|
|
|
|
```js
|
|
function add(a, b) {
|
|
return a + b;
|
|
}
|
|
|
|
console.log(add.call(null, 1, 2)); // 3
|
|
console.log(add.apply(null, [1, 2])); // 3
|
|
```
|
|
|
|
With ES6 syntax, we could write the syntax of `call` using spread operator.
|
|
|
|
```js
|
|
function add(a, b) {
|
|
return a + b;
|
|
}
|
|
|
|
console.log(add.call(null, ...[1, 2])); // 3
|
|
```
|
|
|
|
## Use Cases
|
|
|
|
### Dynamic Function Invocation
|
|
|
|
```js
|
|
function add(a, b) {
|
|
return a + b;
|
|
}
|
|
|
|
console.log(add.call(null, 1, 2)); // 3
|
|
console.log(add.apply(null, [4, 5])); // 9
|
|
```
|
|
|
|
Both `.call` and `.apply` allow dynamic invocation of functions with specific arguments.
|
|
|
|
### Context Management
|
|
|
|
```js
|
|
const person = {
|
|
name: 'John',
|
|
greet() {
|
|
console.log(`Hello, my name is ${this.name}`);
|
|
},
|
|
};
|
|
|
|
const anotherPerson = { name: 'Alice' };
|
|
|
|
person.greet.call(anotherPerson); // Hello, my name is Alice
|
|
person.greet.apply(anotherPerson); // Hello, my name is Alice
|
|
```
|
|
|
|
`.call` and `.apply` can set the this context explicitly when invoking methods on different objects.
|
|
|
|
### Function Borrowing
|
|
|
|
```js
|
|
function greet() {
|
|
console.log(`Hello, my name is ${this.name}`);
|
|
}
|
|
|
|
const person1 = { name: 'John' };
|
|
const person2 = { name: 'Alice' };
|
|
|
|
greet.call(person1); // Hello, my name is John
|
|
greet.call(person2); // Hello, my name is Alice
|
|
```
|
|
|
|
Both `.call` and `.apply` allow borrowing methods from one object and using them in the context of another.
|
|
|
|
### Array Manipulation
|
|
|
|
```js
|
|
const arr1 = [1, 2, 3];
|
|
const arr2 = [4, 5, 6];
|
|
|
|
Array.prototype.push.apply(arr1, arr2);
|
|
|
|
console.log(arr1); // [1, 2, 3, 4, 5, 6]
|
|
```
|
|
|
|
`.apply` is commonly used for concatenating or manipulating arrays by passing them as arguments.
|
|
|
|
## Follow-Up Questions
|
|
|
|
- How do `.call` and `.apply` differ from `Function.prototype.bind`?
|
|
|
|
## Practice
|
|
|
|
- Try implementing your own [`Function.prototype.call` method](/questions/javascript/function-call) and [`Function.prototype.apply` method](/questions/javascript/function-apply) on GreatFrontEnd.
|
|
|
|
## Further Reading
|
|
|
|
- [Function.prototype.call | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
|
|
- [Function.prototype.apply | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
|