题目 25 / 31

为什么调用 arguments[0]() 会让 this.length 读到 3?

知识点: this 绑定难度: 高级

通过成员表达式调用一个值时,this 会绑定到这个表达式是从哪个对象上读出来的——哪怕那个对象是当前调用自己的 arguments 对象。

使用执行可视化器解题在下方逐步观察每个绑定、函数调用和控制台输出。

预测输出结果

预测输出。callback 是通过 arguments[0]() 被调用的,而不是作为裸的 callback()——这会改变 this.length 读到的值吗?

var length = 4;
function callback() {
  console.log(this.length);
}

const object = {
  length: 5,
  method() {
    arguments[0]();
  }
};

object.method(callback, 1, 2);
查看答案与完整解析

正确输出

3

为什么会这样

object.method(callback, 1, 2) 用三个实参调用了 method,因此 method 自己的 arguments 对象的 arguments.length 是 3,索引 0、1、2 上分别保存着 callback、1 和 2。

arguments[0]() 是一次成员表达式调用:被调用的值是通过计算属性访问从 arguments 上读出来的,因此隐式绑定生效,接收者就是这个成员表达式的基对象——也就是 arguments 对象本身,而不是 callback 自己(另外单独创建的、空的)那个 arguments 对象。

因此在 callback 内部,this 就是 method 的 arguments 对象,this.length 读到的是它的 length 属性,也就是 3——既不是外层的变量 length(4),也不是对象字面量上的 length 属性(5),隐式绑定在这里根本不会考虑到它们。

这道题考察什么

  • 隐式绑定取决于调用的语法形式,而不是最终运行的是哪个函数
  • arguments 对象是一个普通对象,调用方完全可以像绑定任何其他接收者一样把 this 绑定到它上面
  • 通过 arguments[i]() 被调用的函数一旦开始运行,会拥有自己独立的、另外的 arguments 对象——this 绑定的是外层那个,而不是内部这个

运行环境前提

假设运行在经典的非严格模式脚本中,回调既不是箭头函数也不在严格模式下,因此隐式绑定可以自由地把 this 绑定到被读出的 arguments 对象上。

规范参考

JavaScript 代码编辑器支持直接编辑或粘贴自定义代码
第 0 步 / 共 0 步
单步Space播放
按 → 单步 或 Space 自动播放
阶段 1: 编译预解析(变量提升与内存分配)
阶段 2: 代码执行(逐行赋值与调用求值)
单步执行原理解析

按键盘右方向键 “→” 进行单步调试,或按空格键 “Space” / 点击 “▶ 自动播放” 进行连续执行。