用 let 或 const 声明的变量是否被提升?

新手上路,请多包涵

我玩 ES6 有一段时间了,我注意到虽然用 var 声明的变量按预期方式提升了……

 console.log(typeof name); // undefined
var name = "John";

…用 letconst 声明的变量似乎在提升方面存在一些问题:

 console.log(typeof name); // ReferenceError
let name = "John";

console.log(typeof name); // ReferenceError
const name = "John";

这是否意味着用 letconst 声明的变量没有被提升?这里究竟发生了什么? letconst 在这件事上有什么区别吗?

原文由 Luboš Turek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 440
2 个回答

@thefourtheye 说这些变量在声明之前 无法访问 是正确的。但是,它比这复杂一点。

letconst 声明的变量是否未被提升?这里究竟发生了什么?

All declarations ( var , let , const , function , function* , class ) 在 JavaScript 中被“提升” 。这意味着如果在范围内声明了名称,则在该范围内标识符将始终引用该特定变量:

 x = "global";
// function scope:
(function() {
    x; // not "global"

    var/let/… x;
}());
// block scope (not for `var`s):
{
    x; // not "global"

    let/const/… x;
}

对于函数作用域和块作用域1都是如此。

The difference between var / function / function* declarations and let / const / class 声明是 初始化

前者使用 undefined 或在范围顶部创建绑定时的(生成器)函数进行初始化。然而,词法声明的变量保持 未初始化状态。这意味着当您尝试访问它时会抛出 ReferenceError 异常。只有当 let / const / class 语句被评估时,它才会被初始化,之前被称为 临时区域 的所有内容。

 x = y = "global";
(function() {
    x; // undefined
    y; // Reference error: y is not defined

    var x = "local";
    let y = "local";
}());

请注意, let y; 语句使用 --- 初始化变量,就像 let y = undefined; undefined 一样。

临时 死区不是句法位置,而是变量(范围)创建和初始化之间的 _时间_。只要不执行该代码(例如函数体或简单的死代码),在声明上方的代码中引用变量就不是错误,如果您在初始化之前访问变量,即使访问代码在声明下方(例如,在过早调用的提升函数声明中)。

letconst 在这件事上有什么区别吗?

不,就吊装而言,它们的工作原理相同。它们之间的唯一区别是 const ant 必须并且只能在声明的初始化部分中分配( const one = 1;const one;one = 2 是无效的)。

1: var 当然,声明仍然只在函数级别起作用

原文由 Bergi 发布,翻译遵循 CC BY-SA 3.0 许可协议

引用 ECMAScript 6 (ECMAScript 2015) 规范的 letconst 声明 部分,

变量是在实例化包含它们的 Lexical Environment 时创建的,但 在评估变量的 LexicalBinding 之前不能以任何方式访问

因此,要回答您的问题,是的, letconst 提升,但在运行时评估实际声明之前您无法访问它们。

原文由 thefourtheye 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题