题目 17 / 31
为什么调用同一个函数的两种方式会打印出不同的值?
知识点: this 绑定难度: 基础
this 完全由调用点的语法形式决定,而不是由函数定义在哪里决定。
使用执行可视化器解题在下方逐步观察每个绑定、函数调用和控制台输出。预测输出结果
预测两行输出。obj.foo() 和 foo2() 调用的是同一个函数对象——为什么结果不一样?
function foo() {
console.log(this.a);
}
var obj = { a: 1, foo };
var a = 2;
var foo2 = obj.foo;
obj.foo();
foo2();查看答案与完整解析
正确输出
1
2为什么会这样
foo 只被声明了一次,随后作为属性挂到了 obj 上。调用 obj.foo() 是一次成员表达式调用,隐式绑定让 this 指向 obj,this.a 读到 1。
foo2 只是一个普通变量,保存着同一个函数对象的引用,调用语法里没有附带任何接收者。
调用 foo2() 是一次无接收者的调用,于是默认绑定生效,this 解析为全局对象,而它的 a 属性早已被 var a = 2 设置为 2,因此结果是 2。
这道题考察什么
- this 绑定在调用点决定,而不是在函数定义处决定
- 以 obj.method() 形式调用时,隐式绑定优先生效
- 把方法拆解到裸变量中会剥离掉隐式绑定
运行环境前提
假设运行在经典的非严格模式脚本中,顶层的 var 声明同时也会成为全局对象的属性,供默认绑定读取。