call、apply 和 bind 是 JavaScript 中用于管理函数执行时 this 指向的方法,它们的核心区别如下:
1. 执行时机
call和apply:立即调用函数并执行。bind:返回一个绑定了this和参数的新函数,需要后续手动调用。
2. 参数传递方式
call:接收参数列表,逐个传递。func.call(thisArg, arg1, arg2, ...);apply:接收参数数组(或类数组对象)。func.apply(thisArg, [arg1, arg2, ...]);bind:接收参数列表(可部分传入),返回的新函数在调用时可继续接收剩余参数。const boundFunc = func.bind(thisArg, arg1); boundFunc(arg2); // 参数合并为 [arg1, arg2]
3. this 绑定特性
call和apply:仅临时修改本次函数调用的this。bind:永久绑定this(除非使用new调用)。后续通过call或apply无法覆盖。const boundFunc = func.bind(obj1); boundFunc.call(obj2); // `this` 仍指向 obj1
4. 与 new 操作符的交互
- 使用
new调用bind返回的函数时,绑定的this会被忽略,转而指向新创建的对象。function Person() {} const BoundPerson = Person.bind({}); const instance = new BoundPerson(); // `instance` 是 Person 的实例
总结表格
| 方法 | 执行时机 | 参数形式 | 返回 | this 绑定是否可变 |
|---|---|---|---|---|
call | 立即执行 | 参数列表 | 无 | 是(仅本次调用) |
apply | 立即执行 | 参数数组 | 无 | 是(仅本次调用) |
bind | 延迟执行 | 参数列表(可部分) | 新函数 | 否(除非 new 调用) |
示例
function greet(greeting, punctuation) {
console.log(`${greeting}, ${this.name}${punctuation}`);
}
const alice = { name: 'Alice' };
// call
greet.call(alice, 'Hello', '!'); // Hello, Alice!
// apply
greet.apply(alice, ['Hi', '?']); // Hi, Alice?
// bind
const boundGreet = greet.bind(alice, 'Hey');
boundGreet('!!'); // Hey, Alice!!
关键区别:call/apply 直接执行并灵活修改 this,而 bind 创建固定 this 的新函数,支持参数柯里化。