可以在JavaScript中使用"let"关键字来避免全局范围的变量吗?

Lor*_*has 5 javascript scope ecmascript-6

我正在用JavaScript进行测试,我注意到使用了let关键字

let variable = "I am a variable";
console.log(window.variable);
Run Code Online (Sandbox Code Playgroud)

没有对象添加variable属性window.这是否意味着它不存在于全球范围内?

我可以声明变量而不必将它们放在函数或IIFE中吗?

我确实搜索过这个,但找不到任何东西.每个人都说要使用类似函数{}()或者只是访问一个包含代码的唯一全局变量,但看到这一点让我想知道它是否可以用于避免这些事情的目的.

小智 17

let语句不能用于以您建议的方式避免全局变量.顶级let语句仍将在全局范围内创建变量,它不会将它们创建为"全局对象"(通常window)的属性.

<script>
  'use strict';
  let fromLet = 'from let';
  var fromVar = 'from var';
</script>

<script>
  console.log(fromLet);        // 'from let'
  console.log(fromVar);        // 'from var'
  console.log(window.fromLet); // undefined
  console.log(window.fromVar); // 'from var'
</script>
Run Code Online (Sandbox Code Playgroud)

此行为主要在第8.1.1.4节:ECMAScript 6规范的全局环境记录中描述.它的要点是有一个全局范围/命名空间,但它的值可以记录在两个不同的地方.全球内置插件,function声明,var声明,和function*(发电机)声明被记录为全局对象的属性,而一切的全球(从let,const,class,等新结构)存储在不暴露内部"环境记录"作为运行时中的对象.

如果您想深入了解细节,可以从以下几个相关摘录中摘录.

全局环境记录用于表示在公共领域(8.2)中处理的所有ECMAScript Script元素共享的最外层作用域.全局环境记录提供了绑定内置全局(第18),所述全局对象的属性,以及用于所有顶层声明(13.2.8,13.2.10一个内发生的)脚本.

可以直接在全局对象上创建属性.因此,全局环境记录的对象Environment Record组件可能包含由FunctionDeclaration,GeneratorDeclarationVariableDeclaration声明显式创建的绑定,以及隐式创建的绑定作为全局对象的属性.为了识别使用声明显式创建的绑定,全局环境记录使用其CreateGlobalVarBindings和CreateGlobalFunctionBindings具体方法维护绑定的名称列表.

表18 - 全球环境记录的附加字段

[[ObjectRecord]]:对象环境记录

绑定对象是全局对象.它包含全局内置绑定以及相关Realm的全局代码中的FunctionDeclaration,GeneratorDeclarationVariableDeclaration绑定.

[[DeclarativeRecord]]:声明性环境记录

包含关联Realm代码的全局代码中所有声明的绑定,但FunctionDeclaration,GeneratorDeclarationVariableDeclaration绑定除外.

[[VarNames]]:字符串 列表

由关联Realm的全局代码中的FunctionDeclaration,GeneratorDeclarationVariableDeclaration声明绑定的字符串名称.