变量提升:
a = 2
var a
console.log(a);//2
我们都知道JS代码是从上到下一行一行执行的,但不完全正确。上面的代码,可能很多人认为,var a 的声明在 a=2之后,所以输出undefined,实际情况却是输出2,再考虑一段代码:
console.log(a)//undefined
a = 2
可能有人认为,a在使用前没进行声明,会抛出异常,但实际上会打印出undefined那么究竟是怎么回事?
实际上引擎在解释Js代码之前会先对其进行编译,编译阶段会找到所有的声明,并用合适的作用域将他们关联起来。也就是说包括变量和函数在内的所有声明都会在代码执行前被预先处理。变量提升其实就是变量的预处理
所以第一段代码表面上是先给a赋值了,然后又定义了一个a,var a,但是实际上var a这一句已经提前执行了,可以看作它被提升到了作用域的最顶部预先执行了,所以真实的代码运行其实是 var a; a = 2;这就是变量提升。可以发现,被提升的仅仅是对变量的声明,赋值操作不会被提升,如果提升改变了代码执行的顺序,会有很严重的后果。
函数声明和变量声明都会被提升,函数会首先被提升,然后才是变量
暂时性死区
ES6添加了let和const用来声明块级作用域的变量和常量。只要块级作用域内存在let命令,它所声明的变量就“绑定”这个区域,不再受外部的影响。ES6 规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为**“暂时性死区”**,也就是说使用let声明的变量都是先声明再使用 ,不存在变量提升问题。
var、let、const区别
var存在提升机制,我们可以在声明之前使用,let,const因为暂时性死区的原因,不能在声明前使用。var一般用来定义全局变量,
let和const都是块级的,且都不可以重复声明,let用来声明变量,const则必须设置初始值,用来声明常量。
值得注意的是,使用const声明引用对象,只能保证引用不改变,修改数组元素或者修改对象属性都是可以的