JavaScript中this关键字绑定规则疑问:两段示例代码执行结果求解
核心前置误区纠正
this 的属性查找和JS的词法作用域是完全独立的两套规则,不存在互相替代的关系,你遇到的问题本质是混淆了「this指向的对象的属性查找」和「普通变量的词法作用域查找」。
示例1执行逻辑解释
function foo() { console.log(this.bar) } var bar = "bar1" foo();
非严格模式下,没有任何前缀的独立函数调用(foo())的this默认绑定到全局对象(浏览器环境是window,Node.js环境是globalThis)。
你用var在全局作用域声明的变量,会自动成为全局对象的属性,相当于window.bar = "bar1",因此this.bar等价于window.bar,最终输出bar1。
补充:如果是严格模式,独立函数调用的
this会是undefined,运行这段代码会直接抛出类型错误。如果把var bar改成let bar/const bar,全局声明不会挂载到全局对象上,也会输出undefined。
示例2执行逻辑解释
function foo() { console.log(this.bar) } var o2 = {foo:foo} console.log(o2.foo())
当函数作为对象的属性被调用时(o2.foo()),this会隐式绑定到调用它的前置对象o2。
你的o2对象只定义了foo属性,没有定义bar属性,this.bar等价于o2.bar,自然输出undefined。
另外你这段代码实际运行会输出两次undefined:第一次是foo内部的console.log输出的o2.bar的值,第二次是外层console.log输出的foo函数的返回值(foo没有主动return,默认返回undefined)。
设计逻辑说明
this的设计初衷是实现「函数上下文的动态绑定」,让同一个函数可以被多个对象复用,不用硬编码绑定死上下文,大幅减少重复代码,比如:
function printName() { console.log(this.username) } const userA = {username: '小王', print: printName} const userB = {username: '小李', print: printName} userA.print() // 输出小王 userB.print() // 输出小李
如果没有this,你需要给每个对象单独写一遍相同的printName函数,或者手动把对象作为参数传入函数,代码冗余度会高很多。
针对你的疑问的明确回答
- 不是调用涉及对象就不采用普通作用域规则:普通作用域规则管的是普通变量的查找,
this的属性查找只负责this这个特殊关键字指向的对象的属性查询,两者互不影响。比如你把示例2的foo内部代码改成console.log(bar),不管你用什么对象调用foo,都会走词法作用域查找,最终输出全局的bar1。
内容的提问来源于stack exchange,提问作者ArunM

