我已经玩了一段时间的ES6,我注意到,而变量声明与var被提升的预期…
console.log(typeof name); // undefined
var name = "John";
...使用let或const声明的变量似乎在提升时存在一些问题:
console.log(typeof name); // ReferenceError
let name = "John";
and
console.log(typeof name); // ReferenceError
const name = "John";
这是否意味着用let或const声明的变量不会被提升?这到底是怎么回事?let和const在这个问题上有什么区别吗?
@thefourtheye说的对,这些变量在声明之前不能被访问。然而,实际情况要比这复杂一些。
使用let或const声明的变量不被提升吗?这到底是怎么回事?
所有的声明(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;
}
对于函数作用域和块作用域都是如此。
The difference between var/function/function* declarations and let/const/class declarations is the initialisation.
The former are initialised with undefined or the (generator) function right when the binding is created at the top of the scope. The lexically declared variables however stay uninitialised. This means that a ReferenceError exception is thrown when you try to access it. It will only get initialised when the let/const/class statement is evaluated, everything before (above) that is called the temporal dead zone.
x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined
var x = "local";
let y = "local";
}());
注意到a let y;语句用undefined初始化变量,如let y = undefined;会。
时间死区不是一个语法位置,而是变量(作用域)创建和初始化之间的时间。在声明上面的代码中引用变量并不是错误,只要该代码没有被执行(例如,函数体或简单的死代码),并且如果你在初始化之前访问变量,即使访问代码在声明下面(例如,在提升的函数声明中被过早调用),它也会抛出异常。
let和const在这个问题上有什么区别吗?
不,就吊装而言,它们的工作原理是一样的。它们之间唯一的区别是常量必须且只能在声明的初始化器部分赋值(const one = 1;,两者都是const one;并且以后像1 = 2这样的重赋是无效的)。
1:当然,var声明仍然只在函数级别上工作