Javascript 为什么不';t const和let语句在窗口对象上定义

Javascript 为什么不';t const和let语句在窗口对象上定义,javascript,Javascript,让我们以以下代码为例: constconsvar='some string'; 让letVar='some string'; var='some string'; (功能(){ console.log(window.constVar);//未定义的打印 console.log(window.letVar);//未定义的打印 console.log(window.varVar);//打印“某些字符串” })();来自 此声明创建一个常量,其作用域可以是声明该常量的块的全局或局部。 与var变量不

让我们以以下代码为例:

constconsvar='some string';
让letVar='some string';
var='some string';
(功能(){
console.log(window.constVar);//未定义的打印
console.log(window.letVar);//未定义的打印
console.log(window.varVar);//打印“某些字符串”
})();来自

此声明创建一个常量,其作用域可以是声明该常量的块的全局或局部。 与var变量不同,全局常量不会成为窗口对象的属性。需要常数的初始值设定项;也就是说,您必须在声明它的同一语句中指定它的值(这很有意义,因为它以后不能更改)

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

一,。为什么使用
var
关键字声明的变量在窗口中定义,而使用
const
let
声明的变量在窗口中未定义

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

类也不会成为全局对象的属性

二,。“全局范围”和浏览器提供给我们的
窗口
对象之间有什么区别

根据规范,有两种类型的底座:

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

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

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

}
如果
以与
const
相同的方式工作,则它们不需要不同的名称。window也从其他位置继承,例如Object.prototype和带有ID的元素。“偶然的”(内在的)全局变量从来都不是一个好主意,所以新的规范在不破坏现有代码的情况下清理了先前JS实现中的“slop”。这稍微超出了JS本身,是一个实现细节;例如,Node.js没有
窗口
let
没有在
窗口
上定义属性的简单原因是,它不应该按照规范在
窗口
上定义属性。因此,它可以按预期运行。你是在问为什么做出这个决定?因为除此之外,唯一的答案是循环“它以这种方式工作,因为它应该以这种方式工作”。MDN中的引语很好,但从字面上看,后面的下一句话是“与var变量不同,全局常量不会成为窗口对象的属性。”—我再次问,这里的问题是什么?因为“这是根据规范工作的,这就是它的工作原理”这不是一个很好的答案,特别是考虑到你应该知道在MDN中查找了它所说的内容。@ScottHunter我刚才是在对语句的块作用域说话为什么
let
在这里的行为像
const
呢?
let
const
在作用域上是一样的。这很有意义(规范基本原理)如果你不得不大胆猜测,你会怎么说,他们在变量赋值语句与
窗口
对象的交互方式和不交互方式上的区别的基本原理是什么?我不确定tbh。将所有内容放在全局对象上并不比将所有内容放在全局范围内更糟糕。但是,全局对象被定义为“主机对象”,这意味着它实际上可以按照实现所需的方式运行。这可能使强制执行
const
绑定变得更加困难(即
const foo=42;window.foo=21;
)@Jonaswillms:在一个环境中总是只有一个全局作用域。一个页面上的所有
都共享同一个环境。全局变量是否也是
窗口的属性都没有区别。@felix哎呀,我真的以为每个脚本都会创建一个新的作用域……那么你关于常量的观点似乎是正确的进入一个好的方向…@jonaswillms:作为模块加载的脚本有模块作用域。