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

Function.prototype.call.call双重调用等价于func()的运行原理解析

执行逻辑推导

整个过程完全遵循ES5规范中Function.prototype.call的定义,没有特殊处理,我们可以把Function.prototype.call.call(func)拆分为两层call调用逐一拆解:

  1. 第一层调用:确定call的执行主体
    Function.prototype.call.call(func)中,最后一个.call的调用主体是Function.prototype.call本身,你可以等价理解为:
const baseCall = Function.prototype.call;
baseCall.call(func);

此时我们先套入call方法的规范执行步骤,这次调用中:

调用call的对象是baseCall本身,传入的thisArg为目标函数func,无额外参数

  • 校验baseCall是可调用对象,校验通过
  • 初始化空参数列表
  • 无额外参数,参数列表保持为空
  • 调用baseCall的[[Call]]内部方法,将thisArg(也就是目标函数func)作为this值传入,空参数列表作为执行参数
  1. 第二层调用:执行baseCall本身的逻辑
    上一步触发了baseCall也就是Function.prototype.call的执行,此时baseCall运行时的this指向就是我们的目标函数func,再次套入call的规范执行步骤:

此时调用call的对象就是目标函数func,没有传入显式的thisArg和额外参数

  • 校验func是可调用对象,校验通过
  • 初始化空参数列表
  • 无额外参数,参数列表保持为空
  • 调用func的[[Call]]内部方法,this值为undefined(非严格模式下自动转为全局对象),空参数列表传入,也就是等价于直接执行func()
    这就是整个操作最终触发func执行的完整逻辑。

等价性说明

Function.prototype.call.call(func)和Function.call.call(func)效果完全一致,是因为Function构造函数本身的call方法继承自Function.prototype.call,二者指向同一个函数,执行逻辑没有任何区别。

扩展验证

我们可以传入参数更直观验证逻辑:

const func = function(content) {
  console.log(`输出内容:${content || '默认值'}`)
}
// 等价于 func('测试')
Function.prototype.call.call(func, undefined, '测试');
// 执行后输出:输出内容:测试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:57:01