`this`的默认绑定与Chrome浏览器和Node.js不同

sam*_*ris 8 javascript scope google-chrome v8 node.js

我正在阅读第2章:this所有人现在都有意义!来自你不了解JS,并决定做这个实验.

我有这个简单的脚本foo.js:

var a = 'foo';
var output;

// lets find a way to output strings in both
// Chrome and Node.js
if (typeof alert === 'undefined') {
    output = console.log;
} else {
    output = alert;
}

function getA() {
    return this.a;
}

var foo = getA();
output(foo);
Run Code Online (Sandbox Code Playgroud)

我期待以下事情getA()被称为:

  1. 由于调用站点getA在全局范围内,getA()将绑定到全局对象.
  2. 由于var a在全局范围内声明,我认为全局对象将具有一个名为的属性a,并且此属性与变量相同a.
  3. 因此,我希望this.a引用变量a.
  4. 因此我希望output(foo)打印字符串foo.

但是,在Node.js(非严格模式)下运行时,这是输出:

$ node foo.js
undefined
Run Code Online (Sandbox Code Playgroud)

然后我在一个简单的HTML页面中包含了相同的脚本,并将其加载到chrome中.

<html>
  <head>
    <script src="foo.js" type="text/javascript"></script>
  </head>
  <body>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,Chrome alert是字符串foo.

为什么Chrome的输出与Node.js不同?

Kyl*_*son 14

由于getA的调用站点在全局范围内,因此getA()将绑定到全局对象.

这是对this我书中约束规则的误解.呼叫站点的位置(又名"在全球范围内")完全无关紧要.这是进行呼叫的方式,而且仅限于此.

它不是重要的地方 getA(),但这getA()是一个普通的正常函数调用.THAT是什么决定了你会得到绑定到全局对象this的这一呼吁.

这里的其他答案是正确的......您的节点主程序运行的范围实际上是一个模块(函数包装),而不是真正的全局范围.


And*_*rov 9

由于getA的调用站点在全局范围内,因此getA()将绑定到全局对象.

不,这不适用于节点 - 你的脚本被包装到一个函数中,所以你的例子实际上就是这个代码:

(function (exports, require, module, __filename, __dirname) {
  var a = 'foo';
  var output;

  // lets find a way to output strings in both
  // Chrome and Node.js
  if (typeof alert === 'undefined') {
    output = console.log;
  } else {
    output = alert;
  }

  function getA() {
    return this.a;
  }

  var foo = getA();
  output(foo);
})(exports, require, module, 'file.js', '/dir/name');
Run Code Online (Sandbox Code Playgroud)


小智 8

NodeJS的行为与浏览器不同.顶级范围不是全局范围,它是该文件或模块中的范围.删除"var",你的代码将在节点环境中工作(一个将成为真正的全局),它将console.log字符串'foo'.

有关完整参考,请参阅以下页面:http://nodejs.org/api/globals.html

要么

如何在node.js中使用全局变量?