题目 19 / 31

为什么最后一行什么都没打印?

知识点: this 绑定难度: 进阶

call 和 apply 会立即以指定的 this 调用函数;bind 只是返回一个新函数。

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

预测输出结果

预测输出。四行代码看起来都在调用 foo——真的都调用了吗?数一数实际出现了几行 console.log。

function foo() {
  console.log(this.a);
}
var obj = { a: 1 };
var a = 2;

foo();
foo.call(obj);
foo.apply(obj);
foo.bind(obj);
查看答案与完整解析

正确输出

2
1
1

为什么会这样

foo() 是一次无接收者的调用,默认绑定生效:this 是全局对象,this.a 读到的是全局变量 a,也就是 2。

foo.call(obj) 和 foo.apply(obj) 都属于显式绑定——它们会立即以 this 被强制指定为 obj 的方式调用 foo,因此两次 this.a 都读到 1。

foo.bind(obj) 根本没有调用 foo。它只是同步地返回一个全新的绑定函数,把 obj 永久附加为它的 this。由于这个返回的函数从未被调用,foo 的函数体不会第四次执行,这一行也就没有任何输出。

这道题考察什么

  • call 和 apply 会立即以显式指定的 this 调用函数
  • bind 返回一个新函数,而不是调用原函数
  • 绑定函数的 this 之后无法被再次的 call、apply 或 bind 覆盖

运行环境前提

假设运行在经典的非严格模式脚本中,默认绑定解析为全局对象,而不是 undefined。

规范参考

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

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