1.块级作用域
1.1Var声明及变量提升(Hosting)机制
在函数作用域中通过关机子var声明的变量,无论实际上是哪里声明的,都会被当成当前作用域顶部声明的变量,这就是我们常说的提升(Hosting)机制
1.2. 块级声明
块级声明用于声明在指定块的组用于之外无法访问的变量。块级作用域(或词法作用域)存在于:
- 函数内部
- 块中(字符{和}之间的区域)
let声明
用let代替var来声明变量,就可以把变量的作用域限制在当前代码块中。Let声明不会被提升,需要把let声明放在封闭代码块的顶部。禁止重声明
假设作用域已经存在某个标识符,此时再使用let关键字声明它就会抛出错误。不管之前是用var还是let声明的。Const声明
使用const声明的是常量,其值一旦被设定后不可更改。因此,每个通过const声明的常量必须进行初始化。
与let类似,在同一作用于用const声明已经存在的标识符也会导致语法错误,无论该标识符是使用var还是let声明的。
无论在严格模式还是在非严格模式下,都不可以为const定义的常量再赋值,否则会抛出错误。
但是用const声明对象时,不允许修改绑定,但允许修改值。这意味着声明对象后,可以修改该对象的属性值。临时死区(Temporal Dead Zone)
与var不同,let和const声明的变量不会被提升到作用域顶部,如果在声明之前访问这些变量,即使是相对安全的typeof操作符也会触发引用错误。
因为,let声明之前,该变量还位于临时死区或TDZ中。Javascript引擎在扫描代码发现变量声明时,要么将他们提升至作用域顶部(var),要么将声明放到TDZ中(let和var),访问TDZ中的变量会粗发运行错误。只有执行过变量声明语句后,变量才会从TDZ中移出,方可正常访问。循环中的块作用域绑定
循环变量用let声明,并且在循环后无法访问到该变量。循环中的let声明
Let声明模仿IIFE所做的一切来简化循环过程,每次迭代循环都会创建一个新变量,并以之前迭代中的同名变量的值将其初始化。循环中的const声明
Const不能用在for循环中,但可以用在for-in和for-of中。但是不能改变key的值。全局块作用域绑定
当var被用于全局作用域时,他会创建一个新的全局变量作为全局对象的属性。这意味着用var可能会无意中覆盖一个已经存在的全局变量。
但是如果你在全局作用域中使用let或const,会在全局作用下创建一个新的绑定,但该绑定不会添加为全局变量的属性。块级绑定最佳实践的进化
默认使用const,只有确实需要改变变量的值时使用let。因为大部分变量的值在初始化后不应再改变,而预料外的变量值的改变是很多bug的源头。