你不知道的ES6知识 - 关于变量声明的方式

块级绑定

概述

ES6不仅引入let和const关键字用于解决变量声明的问题,同时引入了块级作用域的概念

块级作用域:代码执行时遇到花括号,会创建一个块级作用域,花括号结束,销毁块级作用域

var let const 优缺点对比

  1. var 声明的变量会挂载到全局变量window上,进而造成全局变量的污染

    • let 声明的变量不会挂载到window上
  2. var 声明的变量存在 变量提升,可以在定义变量前访问,只是访问到的值为undefined,并不会报错

    • let 声明的变量不存在变量提升,在声明之前访问会报错( ReferenceError )
      • 这里我们留下一个疑问,通常情况下我们访问一个没有定义的变量,抛出的错误应该是: Uncaught ReferenceError: a is not defined,但是为什么这里抛出的错误却是Uncaught ReferenceError: Cannot access ‘a’ before initialization ?
    console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
    let a = 1
    
  3. var 声明的变量允许重复声明,会造成数据被覆盖

    • let 不能在同一个块级作用域内声明同一个变量
        let a = 1
        let a = 2 // Uncaught SyntaxError: Identifier 'a' has already been    declared
    
  4. const 拥有let的所有优点,唯一与 let 有区别的地方就是,const定义的变量是不可改变的,这里的不可改变指的是变量的内存空间内不能发生改变

    • const 在声明变量时必须赋值
    •  const a = 1
       a = 2 // Uncaught TypeError: Assignment to constant variable.
      
    • 但是当我们定义一个对象或者数组(复杂数据类型)时,我们需要注意的时是可以对其中的值进行修改的,所以这里我们一定要清楚的认识到const只是不允许 变量的内存空间内不能发生变化,但是并没有限制该内存空间的指针指向的那个内存空间里的值不能发生变化
      const obj = {} // 此时obj存储的是一个地址指针,该指针指向的是一块存有对象的内存空间
      obj.name = '61' // 这里我们修改的obj内存储的那个指针指向的内存空间,并没有修改obj内存中存储的这个指针
      console.log(obj) // {name: '61}
    

在声明let前,访问let的报错问题(Cannot access ‘a’ before initialization)

  1. 其实在底层实现上,let的声明还是会存在变量提升的,只不过这次的提升会将变量放置到一个黑盒子中,这个黑盒子ES6定义为"暂时性死区",当你在let或者const声明的变量之前使用时,暂时性死区就会发生作用,给你抛出"Cannot access ‘a’ before initialization"这样的错误,当程序执行到该变量声明时才会从暂时性死区中移出
    • 所以我们上面理解成为不存在变量提升也是可以的,只是我们需要清楚暂时性死区这个东西的存在

for循环中对于let的处理

  1. 在for循环中,会进行特殊的处理,即在每次进入循环体的时候都会开启一个新的作用域,并且将循环变量绑定至该作用域内上(每次循环都是一个新的循环变量)
    • 在for循环中使用let声明的循环变量,在循环体结束时会被销毁,所以在外部是无妨访问的
    <!-- var 将变量提升至全局作用域内,并挂载到window上 -->
    for (var i = 0 ; i < 10 ; i++) {
      // TODO
      }
    console.log(i) // 10
    
    <!-- let 在循环体结束后会销毁循环变量 -->
    for (let i = 0 ; i < 10 ; i++) {
      // TODO
    }
    console.log(i) // Uncaught ReferenceError: i is not defined
    

你可能感兴趣的:(ES6)