我玩 ES6 有一段时间了,我注意到虽然用 var
声明的变量按预期方式提升了……
console.log(typeof name); // undefined
var name = "John";
…用 let
或 const
声明的变量似乎在提升方面存在一些问题:
console.log(typeof name); // ReferenceError
let name = "John";
和
console.log(typeof name); // ReferenceError
const name = "John";
这是否意味着用 let
或 const
声明的变量没有被提升?这里究竟发生了什么? let
和 const
在这件事上有什么区别吗?
原文由 Luboš Turek 发布,翻译遵循 CC BY-SA 4.0 许可协议
@thefourtheye 说这些变量在声明之前 无法访问 是正确的。但是,它比这复杂一点。
All declarations (
var
,let
,const
,function
,function*
,class
) 在 JavaScript 中被“提升” 。这意味着如果在范围内声明了名称,则在该范围内标识符将始终引用该特定变量:对于函数作用域和块作用域1都是如此。
The difference between
var
/function
/function*
declarations andlet
/const
/class
声明是 初始化。前者使用
undefined
或在范围顶部创建绑定时的(生成器)函数进行初始化。然而,词法声明的变量保持 未初始化状态。这意味着当您尝试访问它时会抛出ReferenceError
异常。只有当let
/const
/class
语句被评估时,它才会被初始化,之前被称为 临时区域 的所有内容。请注意,
let y;
语句使用 --- 初始化变量,就像let y = undefined;
undefined
一样。临时 死区不是句法位置,而是变量(范围)创建和初始化之间的 _时间_。只要不执行该代码(例如函数体或简单的死代码),在声明上方的代码中引用变量就不是错误,如果您在初始化之前访问变量,即使访问代码在声明下方(例如,在过早调用的提升函数声明中)。
不,就吊装而言,它们的工作原理相同。它们之间的唯一区别是
const
ant 必须并且只能在声明的初始化部分中分配(const one = 1;
,const one;
像one = 2
是无效的)。1:
var
当然,声明仍然只在函数级别起作用