题目 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 对象上。