变量是用 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";

这是否意味着使用或未吊装的变量声明?这到底是怎么回事?在这件事上和之间有什么区别吗?letconstletconst


答案 1

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

变量是用吊装声明的还是不吊装的?这到底是怎么回事?letconst

所有声明 (, , , , , ) 都在 JavaScript 中“提升”。这意味着,如果在作用域中声明名称,则在该作用域中,标识符将始终引用该特定变量:varletconstfunctionfunction*class

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

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

    let/const/… x;
}

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

声明和 // 声明之间的区别在于初始化
前者在作用域顶部创建绑定时,会立即使用或(生成器)函数进行初始化。然而,词法声明的变量保持未初始化。这意味着当您尝试访问它时,将引发异常。只有当 // 语句被评估时,它才会被初始化,(上面)之前的所有内容都称为时间盲区varfunctionfunction*letconstclassundefinedReferenceErrorletconstclass

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

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

请注意,语句使用 like have 初始化变量。let y;undefinedlet y = undefined;

时空盲区不是句法位置,而是变量(作用域)创建和初始化之间的时间。只要代码未执行(例如,函数体或只是死代码),在声明上方的代码中引用变量就不是错误,并且如果在初始化之前访问变量,即使访问代码低于声明(例如,在调用过早的提升函数声明中),也会引发异常。

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

不,就吊装而言,它们的工作原理相同。它们之间的唯一区别是,蚂蚁必须并且只能在声明的初始部分进行赋值(两者和后来的重新赋值都是无效的)。constconst one = 1;const one;one = 2

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


答案 2

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

当实例化变量包含的词法环境时,将创建变量,但在评估变量的词法绑定之前,不得以任何方式访问这些变量

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