call和apply的作用以及使用场景
JavaScript 中的 call 和 apply 方法用于显式绑定函数的执行上下文(this 值),并在调用函数时传递参数。它们的核心区别在于参数的传递方式,这决定了它们在不同场景下的适用性。
作用
-
改变
this的指向
强制将函数内的this绑定到指定对象,使函数在特定上下文中执行。const obj1 = { name: "Alice" }; const obj2 = { name: "Bob" }; function greet() { console.log(this.name); } greet.call(obj1); // 输出 "Alice" greet.apply(obj2); // 输出 "Bob" -
传递参数
call: 以参数列表形式传递(func.call(thisArg, arg1, arg2, ...)。apply: 以数组或类数组形式传递(func.apply(thisArg, [argsArray])。
区别
| 方法 | 参数传递方式 | 适用场景 |
|---|---|---|
call |
逐个参数传递(逗号分隔) | 参数数量已知、明确的情况 |
apply |
参数通过数组传递 | 参数数量不确定或已存在数组时 |
使用场景
1. 借用其他对象的方法
当一个对象需要借用另一个对象的方法时:
const arrayLike = { 0: "a", 1: "b", length: 2 };
// 借用数组的 push 方法
Array.prototype.push.call(arrayLike, "c"); // arrayLike 变为 {0: "a", 1: "b", 2: "c", length: 3}
2. 实现继承(构造函数链)
子类构造函数中调用父类构造函数:
function Parent(name) {
this.name = name;
}
function Child(name, age) {
Parent.call(this, name); // 继承 Parent 的属性
this.age = age;
}
3. 处理参数数组
将数组展开为参数列表(ES6 之前常用):
const numbers = [1, 3, 5, 2];
const max = Math.max.apply(null, numbers); // 输出 5
// ES6 替代方案:Math.max(...numbers)
4. 操作类数组对象
将类数组(如 arguments、DOM 节点列表)转换为真实数组:
function example() {
const args = Array.prototype.slice.call(arguments); // 转为数组
// ES6 替代方案:const args = Array.from(arguments);
}
5. 明确函数上下文
确保回调函数或事件处理函数中的 this 指向正确:
const handler = {
message: "Hello",
handleClick() { console.log(this.message); }
};
button.addEventListener("click", () => {
handler.handleClick.call(handler); // 强制 this 指向 handler
});
// 更简洁的方案:使用 bind()
button.addEventListener("click", handler.handleClick.bind(handler));
总结
- 优先使用
call:当参数明确且数量固定时。 - 优先使用
apply:当参数已存在数组中或数量不确定时。 - ES6+ 替代方案:展开运算符(
...)和Array.from()减少了apply的使用,但call/apply在兼容性要求高或特定场景下仍有价值。

浙公网安备 33010602011771号