为什么不在 window 对象上定义 const 和 let 语句

IT技术 javascript
2021-01-25 12:25:56

我们以下面的代码为例:

const constVar = 'some string';
let letVar = 'some string';
var varVar = 'some string';

(function() {
  console.log(window.constVar); // prints undefined
  console.log(window.letVar); // prints undefined
  console.log(window.varVar); // prints 'some string'
})();

根据constmdn声明的描述:

这个声明创建了一个常量,其作用域可以是全局的,也可以是声明它的块的局部的。

我假设let以同样的方式工作。

在这种情况下,“块”包含在全局范围内。我想这里的重要区别是,虽然const constVar是“全局”可访问的,但它仍然没有在window对象上定义它

这让我认为全局范围和window对象是不同的。这最终导致 2 个问题。

  1. 为什么使用var关键字 get 定义的window变量const使用let未定义的变量定义在window

  2. “全局范围”和window浏览器提供给我们对象有什么区别

2个回答

1. 为什么使用var关键字 get 定义的变量在 window 上定义,而使用constlet未定义在 window 上的变量

因为规范是这么说的。如果您要询问该决定背后的原因,那么您应该联系规范维护者。

顺便说一句,类不会成为全局对象的属性。

2.“全局范围”和window浏览器提供给我们对象有什么区别

根据规范,有两种类型的基础环境记录

  • 声明性环境记录
  • 对象环境记录

一个声明环境记录基本上是你的标准环境,你调用函数时。所有绑定(变量、常量等)都定义在一些无法从普通代码访问的内部数据结构中。

一个对象环境记录,另一方面用一个实际的JavaScript对象来存储绑定。例如,现在已弃用的with语句使用了它:

with({foo: 42}) {
  console.log(foo);
}

现在,一个全局环境记录实际上由两个环境记录组成:一个声明性环境记录和一个对象环境记录。对象环境由全局对象支持,即window包含var浏览器提供的声明和其他全局变量。该声明的环境包含letconstclass,等声明。

这是有道理的(规范基本原理)如果你不得不冒险做出最好的猜测,你会说他们在变量赋值语句之间关于它们如何交互或不与window对象交互的区别的基本原理是什么
2021-03-19 12:25:56
@JonasWilms:作为module加载的脚本有module范围。
2021-03-27 12:25:56
我不确定 tbh。将所有内容放在全局对象上并不比将所有内容放入全局范围更糟糕。但是,全局对象被定义为“宿主对象”,这意味着它实际上可以按照实现的需要进行操作。也许这使得强制执行const绑定变得更加困难(即const foo = 42; window.foo = 21;)。
2021-03-30 12:25:56
@felix oop,我实际上认为会为每个脚本创建一个新脚本......然后你关于常量的观点似乎朝着一个好的方向发展......
2021-03-31 12:25:56
@JonasWilms:环境中始终只有一个全局范围。<scripts>页面上的所有内容共享相同的环境。全局变量是否也是 的属性window没有区别。
2021-04-01 12:25:56

来自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

这个声明创建了一个常量,其作用域可以是全局的,也可以是声明它的块的局部的。 与 var variables 不同,全局常量不会成为 window 对象的属性需要一个常量的初始化程序;也就是说,您必须在声明它的同一个语句中指定它的值(这是有道理的,因为它以后不能更改)。

要回答您的第二个问题,可以通过 window 对象访问全局变量。但是,const 有一个例外。

那么为什么let表现得像const这里?
2021-03-20 12:25:56
let并且const在范围方面是相同的。
2021-03-21 12:25:56