1.var声明与变量提升
使用var关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于函数的顶部(如果声明不在函数内,则视为全局作用域的顶部),这就是所谓的变量提升,例子如下:
注:value变量的声明会被提升到函数的顶部,而初始化赋值操作则留在了原地,这代表在else分支内也可以正确的访问value变量而不会报错。
2.块级声明
注:块级声明就是让所声明的变量不能在块级作用域外进行访问,块级作用域又被称为词法作用域,在如下的情况下会被创建:
1.在一个函数内部
2.在一个由一对花括号包裹的代码块内部({})
let声明
let声明的语法与var的语法一致,但let会将变量的作用域限制在当前的代码块中。let声明并不会被提升,因些若想在变量在整个代码块内部可以使用,需手动将let声明放置到代码块的顶部。如var例子修改为let后:
禁止重复声明
如果在代码块内部一个标识符已被定义,那么在此代码块中使用同一个标识符进行let声明则会报错。
常量声明
使用const声明的变量被认为是常量,常量的值在被初始化后过后是不可修改,所有const声明的变量必须在声明时进行初始化操作。
对比常量声明与let声明
相同点:
- 在代码块内使用let与const声明都不允许在代码块外部进行使用,即声明不会被提升。- 如在代码块内部一个标识符已被定义,那么在些代码块中let和const则不能对这个标识符进行声明,否则则会报错处理。
不同点:
- let声明赋值后可修改,const声明赋值后不可修改(注:const声明的对象可修改,因对象为引用类型)。
使用const声明对象
const声明会阻止对于变量绑定及变量自身值的修改,但不会阻止变量成员的修改。
暂时性死区(TDZ)
使用let和const声明的变量,在达到声明位置之前都是无法访问的,如果试图访问会导致报错,在达到声明位置之前无法被访问的区域被称为暂时性死区。
当JS引擎扫描代码块并发现变量声明时,它会处理var声明时将声明提升到函数的顶部,而let和const则会将声明放入暂时性死区。任何在暂时性死区访问let和const声明的变量时就会导致报错。只有执行到了let和const声明后,该变量才会从暂时性死区内被移除,才可以安全使用。
3.循环中的块级绑定
循环中的块级绑定

如上图,开发者或许最期望在for循环内使用块级作用域,也就是想让一次性的循环计数器仅能在for循环内部使用。但这个例子在其他默认使用块级作用域语言中能够按照预期工作,也就是在for循环中能访问到变量i,但在JS中,var声明导致了变量提升,循环结束后,依旧可以在循环体外部访问到变量i,如果把var改为使用let声明的话,就会看到循环后,无法在循环外部访问到变量i
4.全局块级绑定
在全局作用域 中,如window已存在需要声明的标识符,在使用var声明时,会覆盖window中已经存在的标识符,如果使用let或const声明则会在全局作用域上创建新的绑定,但不会有任何属性加到全局对象上,这也就意味着使用let或const不会覆盖一个全局变量,你只能将其遮蔽。
5.块级绑定新的最佳实践
默认情况 下应使用let代替var声明,如遇到需要受保护的变量则使用const声明。
6.总结
let与const块级绑定将词法作用域引入了JS,这种声明方式都不能进行变量提升,并且仅在它们的代码块内部可用。这样变量就可以在必要位置被准确声明。let与const有一个副作用,就是不能在变量声明位置之前访问它们,由于块级绑定存在暂时性死区,试图在声明位置之前访问它就会导致报错。
