You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js与Node.js REPL的区别及《You Don't Know JS》代码运行疑问

解析《You Don't Know JS》中this绑定的代码行为

嘿,我最近正在钻研《You Don't Know JS》系列,刚看到第三本书第2章“'this' All make sense now”里的这段代码,立刻动手用Node.js v8.11.1跑了一遍,发现里面的this绑定逻辑挺值得琢磨的:

function foo() { console.log( this.a ); }
function doFoo(fn) {
  // `fn` is just another reference to `foo`
  fn(); // <-- 这里是关键的调用位置!
}
var obj = { a: 2, foo: foo };
var a = "oops, global"; // 全局作用域下的a
doFoo( obj.foo ); // 输出 "oops, global"

我把这段代码存成了foo.js,执行node foo.js命令时,结果和书中描述的一致(如果是在全局环境下运行的话)。这里的核心点在于函数调用位置(call-site)决定了this的绑定对象:

  • 当我们把obj.foo作为参数传给doFoo时,本质上是把foo函数的引用单独抽离了出来——相当于在doFoo内部调用的是一个“独立”的函数,而不是obj的方法。
  • 在非严格模式下,这种独立调用的函数,this会默认绑定到全局对象:
    • 浏览器环境中,全局对象是window,var a会自动挂载到window上,所以this.a就是"oops, global";
    • 如果是在Node.js的模块文件中运行,情况会有点不一样:模块顶层的var a属于模块作用域,不会挂载到global对象上,此时fn()调用时this绑定到module.exports(空对象),所以会输出undefined;但如果是在Node.js的REPL全局环境下运行,var a会挂载到global上,结果就和书中一致了。

简单来说,只要函数不是作为对象方法、不是用call/apply/bind指定this、不是作为构造函数调用,非严格模式下this就会绑定到全局对象——这就是为什么这段代码会输出"oops, global"而不是我们预想的2。

内容的提问来源于stack exchange,提问作者Daniele Paolini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:06:42