1

我正在阅读“你不知道 JS”系列丛书,并尝试运行该片段:

function foo() {
  console.log( this.a );
}

function doFoo(fn) {
  // `fn` is just another reference to `foo`

  fn(); // <-- call-site!
}

var obj = {
  a: 2,
  foo: foo
};

var a = "oops, global"; // `a` also property on global object

doFoo( obj.foo ); // "oops, global"

(您可以在 3d 书的第 2 章中找到它:'this' All make sense now

如果我将它保存到 'foo.js' 并使用节点 foo.js (v 8.11.1) 运行它,那么我得到undefined. 如果我启动节点 REPL 并输入相同的代码,我会得到:

> function foo() { console.log(this.a); }
undefined
> function doFoo(fn) { fn(); }
undefined
> var obj = { a:2, foo:foo };
undefined
> var a = "oops, global";
undefined
> doFoo(obj.foo);
oops, global
undefined

正如书中所预料的那样。Firefox 开发控制台上的结果相同。

如果我删除声明并只留下分配,a = "oops, global"那么它会在 REPL 和 Node.js 上按预期运行。这对我来说更有意义,因为通过这种方式我在全局对象上设置了一个属性,而在“原始”方式中我只是声明了一个变量。

谁能向我解释这种行为?谢谢你们。

编辑:我想我已经接近解决方案了,我注意到如果我制作的脚本foo.js只包含:

var x = 42;
console.log(this);

我得到了{},所以x没有附加到全局对象。如果我启动 Node.js REPL 并输入相同的代码,我会得到一个x附加的大对象:

{
   ...
   x: 42
}

所以我认为区别在于“谁是全局对象?” 在 REPL 和 Node.js 中。

4

1 回答 1

1

当您在 Node.js 中运行该文件时,您var a实际上并不是在全局范围内,而是在函数范围内——一个模块函数范围(更多信息请参见此处)。基本上,文件的所有内容都像在函数内一样运行。var a实际上在该功能范围内也是如此。

而在 REPL 中,它确实是在全球范围内。

于 2018-04-16T10:14:23.260 回答