在es中存在函数提升和变量提升,函数提升优于变量提升。函数提升会把函数定义挪到整个作用域的顶部。变量提升把变量的定义挪到作用域顶部,但是不赋值。
因为变量提升,所以代码中变量可以在定义前使用。
当有多个同名变量声明的时候,函数声明会覆盖其他的声明。如果有多个函数声明,则是由最后的一个函数声明覆盖之前所有的声明。
es6中新增的let和const关键字没有变量提升,同时他们有块级作用域。
块级作用域中存在let和const关键字,作用域中的变量和它们绑定,不再受外部的影响,不能在定义前使用。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ。

var tmp = 123;

if (true) {
   tmp = 'abc'; // ReferenceError
   let tmp;
}

变量就近原则和暂时性死区结合下的结果

let b = 1;

function test4() {
    console.log(b);  //1
    let a = 2;
}
test4()


let b = 1;

function test4() {
    console.log(b);  //not defined
    let b = 2;
}
test4()