我认为 const 和 let 就像 var 一样被提升,但这让我相信我错了。
并不真地,let
and const
确实被吊起,或者我喜欢这样称呼它,half- 吊起。之间有两个很大的区别var foo
and let foo
:范围和初始化。您已经了解范围差异。第二个是与var foo
, 这俩宣言和初始化 (with undefined
) of foo
被吊起。和let
, 只有宣言 of foo
被吊起,而不是初始化. foo
只是已初始化当代码的单步执行达到let foo
陈述。您不能使用(读取或写入)未初始化的标识符。不能使用标识符的这段时间称为暂时死区 (TDZ)。
即使var
,提升的初始化是初始化undefined
,不是右侧的值=
:
console.log(typeof foo); // "undefined"
foo(); // TypeError: foo is not a function
var foo = () => {};
您所做的更改,移动了声明getRandom
在第一次使用它之前进行准备是正确的做法。 (或者使用函数声明,因为声明作为一个整体[包括函数的创建]被提升。)
我们来看看这个半吊装的东西:
let foo = "outer";
function x()
{
console.log("...");
let foo = "inner";
console.log(foo);
}
x();
(let
and const
有块作用域,但我正在使用一个函数,因为我将与var
一会儿。)
Within x
,那个内在foo
不能使用,直到let foo
line. But,你无法访问外部foo
它上面;这失败了:
let foo = "outer";
function x()
{
console.log(foo); // ReferenceError: `foo` is not defined
let foo = "inner";
console.log(foo);
}
x();
这就是半吊装:宣言的内在的foo
已提升,但变量未提升已初始化直到let foo
陈述。这意味着你不能使用foo
完全高于(甚至不是来自包含范围)let foo
线。内部foo
遮蔽外部foo
贯穿整个函数,但在初始化之前您不能使用它。这涵盖在Let 和 Const 声明 https://tc39.es/ecma262/#sec-let-and-const-declarations在规格中。
这与var
:
var foo = "outer";
function x()
{
console.log(foo); // undefined
var foo = "inner";
console.log(foo); // "inner"
}
x();
这运行得很好,因为两个声明and的初始化foo
(with undefined
) 被提升到函数的顶部。 (吊装后,var foo = "inner";
行变成一个简单的赋值语句。)所以内部foo
遮蔽外部foo
整个过程中,也可以在整个过程中访问,最初使用其默认值(undefined
) 以及后来的"inner"
(一旦分配给它)。
由于 TDZ 是时间性的(与时间相关),而不是空间性的(与范围内的空间或位置相关),因此您可以使用由let
or const
(or class
) above它的声明,只是不before它的声明。这失败了,因为getNumber
尝试访问theNumber
before它已初始化,同时仍在 TDZ 中:
const getNumber = () => theNumber;
console.log(getNumber()); // ReferenceError
let theNumber = 42;
这有效是因为getNumber
访问theNumber
after它已初始化:
const getNumber = () => theNumber;
let theNumber = 42;
console.log(getNumber()); // 42