2804. call vs apply vs bind
2023年5月2日大约 2 分钟
2804. call vs apply vs bind
Problem: 2804. 数组原型的 forEach 方法
/**
* apply
*/
Array.prototype.forEach = function (callback, context) {
const values = this;
for (let i = 0; i < values.length; i++) {
callback.apply(context, [values[i], i, values])
}
}
/**
* call
*/
Array.prototype.forEach = function (callback, context) {
const values = this;
for (let i = 0; i < values.length; i++) {
callback.call(context, values[i], i, values)
}
}
/**
* bind 参数可以预绑定
*/
Array.prototype.forEach = function (callback, context) {
const values = this;
for (let i = 0; i < values.length; i++) {
callback.bind(context, values[i], i, values)();
}
}
Array.prototype.forEach = function (callback, context) {
const values = this;
for (let i = 0; i < values.length; i++) {
callback.bind(context)(values[i], i, values);
}
}
Array.prototype.forEach = function (callback, context) {
const values = this;
for (let i = 0; i < values.length; i++) {
callback.bind(context,values[i], i)( values);
}
}| 方法 | 描述 | 是否立即执行 | 是否返回新函数 | 参数格式 |
|---|---|---|---|---|
call | 使用指定的 this 值和若干参数调用函数 | ✅ 是 | ❌ 否 | 逗号分隔参数 |
apply | 使用指定的 this 值和参数数组调用函数 | ✅ 是 | ❌ 否 | 参数数组 |
bind | 返回一个绑定了 this 和部分参数的新函数 | ❌ 否 | ✅ 是 | 逗号分隔(可预绑定) |
题目要点
「2804. call vs apply vs bind」的核心是函数调用语义差异:this 如何绑定、参数何时注入、返回值是结果还是新函数。
思路拆解
- 先统一
forEach的行为目标,再分别用call、apply、bind实现同一调用效果。 - 对比三者差异:
call/apply立即执行,bind返回已绑定函数后再执行。 - 明确参数形态:
call逐个传参,apply传数组,bind可做预绑定。
复杂度分析
- 时间复杂度:三种写法均为
O(n),n为数组长度。 - 空间复杂度:
call/apply为O(1);bind写法会额外创建函数对象,常数开销更高。
边界与测试
- 空数组与稀疏数组(hole)是否按预期处理。
context为null/undefined时的this行为。- 回调抛错时是否中断迭代并透传异常。
工程实践
生产代码中优先选择 call 或原生调用方式;bind 适合确实需要预绑定参数的场景,避免在循环中频繁创建函数。
总结
掌握三者差异的关键是抓住“是否立即执行”和“参数传递形态”两条主线,再结合具体调用场景选择实现方式。
