深入理解ES6-第1章-块级作用域绑定

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的源头。