You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript中call方法调用Array原型方法失败?

问题:为什么用f_timeit(Array.prototype.reduce.call)会报错?

我正在研究JavaScript特性以加深对该语言的理解。在以下示例中,我尝试使用call方法调用数组对象的Array.prototype.reduce方法,我知道其他实现方式,但好奇为何这段代码无法运行?

代码

const f_timeit = (f) => {
  return function(...args) {
    util.p(`Entering function ${f.name}`);
    const start_time = Date.now();
    try {
      return f(...args);
    } finally {
      util.p(`Exiting ${f.name} after ${Date.now() - start_time}ms`);
    }
  }
};

const rarr = [...Array(10000000)].map(e => ~~(Math.random() * 20));

// 这段可以正常运行
console.log(f_timeit((arr) => {
  return arr.reduce((acc, val) => acc + val, 0);
})(rarr));

// 这段运行失败
util.p(f_timeit(Array.prototype.reduce.call)(rarr, (acc, val) => acc + val, 0));

错误信息

return f(...args);
               ^
TypeError: f 不是一个函数

原因分析

Array.prototype.reduce.call并不是一个独立可直接调用的函数——它本质是Function.prototype.call方法的引用,但这个引用脱离了原本的上下文(也就是reduce方法)。当你把call作为参数传给f_timeit时,它只是一个普通函数,不再和reduce绑定。

当f_timeit内部执行f(...args)时,相当于直接调用call(...args),但call方法必须依赖它的this指向(也就是目标函数reduce)才能正常工作。此时this默认指向全局对象(严格模式下为undefined),导致call无法找到要执行的目标函数,最终抛出“不是函数”的错误。

解决方法

方法1:用箭头函数包装上下文

用箭头函数包裹Array.prototype.reduce.call,确保调用时上下文正确:

util.p(f_timeit((arr, accFn, init) => {
  return Array.prototype.reduce.call(arr, accFn, init);
})(rarr, (acc, val) => acc + val, 0));

方法2:通过bind绑定上下文

使用bind把call的this固定为reduce方法,生成一个带绑定上下文的新函数:

util.p(f_timeit(Function.prototype.call.bind(Array.prototype.reduce))(rarr, (acc, val) => acc + val, 0));

内容的提问来源于stack exchange,提问作者Validus Oculus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:05:46