let 声明被提升但未初始化是什么意思?

What does it mean to say let declarations are hoisted but not initialized?

我知道下面的代码片段会导致 ReferenceError:

console.log(b);
let b = 3;

而且我读到如果我们使用 var 而不是 let 就不会失败。
MDN documentations,声称 let 声明也被提升,但它们未被 初始化
令我困惑的是初始化,当我们谈论 ReferenceError 时它甚至有什么关系。

在下面的代码中,

let b;
console.log(b);
b = 3;

初始化写在 console.log(b) 之后,但这不会产生任何 ReferenceError,所以说在第一个片段中抛出异常是没有意义的,因为变量没有被初始化。

谁能澄清一下这些事情?

The let (and const) declaration will throw an error if accessed before initialized.

什么意思?

如果在程序到达声明行之前尝试访问变量,您将收到错误消息:

try{
  console.log(b)
}catch(e){
  console.error(e) //ReferenceError
}

let b //b initalized here (b===undefined)

console.log(b) //undefined
b=3   //Reassign b with 3
console.log(b) //3

即使 let 缺少 =value 部分也会进行初始化,在本例中,值为 undefined,因此它不会再抛出错误。

这就是为什么你不能从 const 声明中省略 =value 部分的原因:它将用 undefined 初始化并且以后不能重新分配。

另请注意 这种错误与尝试访问 undefined 变量时的错误不同:前者甚至会抛出如果定义了变量(在另一个范围内):

let b=1
console.log(b) //1
{
  //Different scope
  try{
    console.log(b)
  }catch(e){
    console.error(e) //ReferenceError: the inner b shadows the outer, but not yet initialized
  }
  let b=2
  console.log(b) //2
}