JavaScript 不应将绑定添加到全局对象,浏览器、Node 和 jsfiddle 中的行为不同

JavaScript let binding should not be added to global object, different behaviour in browser vs Node vs jsfiddle

MDN documentation about let 中,我找到以下一段文字:

"At the top level of programs and functions, let, unlike var, does not create a property on the global object."

以及随附的示例代码:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

当我像这样将此代码添加到 HTML 文件时:

<html>

<head>
  <script type="text/javascript">
    var x = 'global';
    let y = 'global';
    console.log(this.x); // "global"
    console.log(this.y); // undefined
  </script>
</head>

<body>
  <h1>foo</h1>
</body>

</html>

我在控制台中得到了预期的输出:

global
undefined

但是,如果我 运行 我得到节点中的代码:

undefined
undefined

如果我 运行 在 JSFiddle 中使用相同的代码,我也会得到:

undefined
undefined

为什么会这样?全局对象在不同 运行 时间环境中的行为是否不同?此行为记录在何处?

或者在这些情况下 "the top level of programs" 有什么不同吗?

谢谢!

顶层在node.js中确实不一样。请尝试以下操作:

// get access to the global object e.g. window, global
var g = (new Function('return this;'))();
var x = 1;
let y = 2;
console.log(typeof x); // 'number'
console.log(typeof y); // 'number'
console.log(typeof g.x); // 'undefined'
console.log(typeof g.y); // 'undefined'

你的代码 'works' 在节点中的原因是在 node.js 中顶层的范围是模块,而不是像浏览器那样的全局环境(这是 [=22 的一个很好的特性=] 由于遗留原因,浏览器无法添加)。因此,您的 let 语句创建了一个模块级绑定。但是,如果您要从另一个模块导入该模块:

require('./path/to/module/with/xandy');
console.log(typeof x); // 'undefined'
console.log(typeof y); // 'undefined'

绑定未跨模块边界共享。

至于 fiddle,我只能假设他们正在执行某种沙盒,阻止您的 fiddle 代码按预期工作。