js let变量在初始化之前访问为什么会出错?

ES6之前只有全局作用域和函数作用域
这段代码里的if不存在块级作用域,所以被提升到了函数test的作用域内部

1
2
3
4
5
6
7
var a = 100;
function test() {
console.log(a); // undefined
if (false) {
var a = 1;
}
}

同样一段代码用let,会输出100,因为let,const会创建块级作用域。
注意:如果把代码改成if (false) let a =1就会报错:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#description

1
2
3
4
5
6
7
var a = 100;
function test() {
console.log(a); // 100
if (false) {
let a = 1;
}
}

既然有let,块级作用域还有声明提升,那如下代码为什么会抛出错误呢?

1
2
3
4
5
var a = 100;
function test() {
console.log(a); // Throw an error
let a =1
}

我们可以通过浏览器的dev tools来查看详情:

当断点在console.log准备执行的时候,可以看到a其实已经是undefined。
那为什么浏览器要阻止我们提前访问let定义的变量呢?
原因在ECMAScript里规定了

14.3.1 Let and Const Declarations

在NOTE中已经说明:
may not be accessed in any way until the variable’s LexicalBinding is evaluated.