ES6 let 和 const

37 阅读3分钟

Date: 2018-10-20

let

  • 只在代码块内有效

  • 不存在变量提升(只能先声明后使用)(变量提升指变量在声明之前使用,值为ReferenceError)

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    
  • 暂时性死区(声明之前变量不可用)(暂时性死区简称“TDZ”) 例1:

    
    var tmp = 123;
    
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    

    例2:

    if (true) {
      // TDZ开始
      tmp = 'abc'; // ReferenceError
      console.log(tmp); // ReferenceError
    
      let tmp; // TDZ结束
      console.log(tmp); // undefined
    
      tmp = 123;
      console.log(tmp); // 123
    }
    

    例3:

    typeof x; // ReferenceError
    let x;
    
  • 不允许重复申明(不允许在相同作用域内重复声明同一个变量) 例1:

    // 报错
    function () {
      let a = 10;
      var a = 1;
    }
    
    // 报错
    function () {
      let a = 10;
      let a = 1;
    }
    

    例2:

    function func(arg) {
      let arg; // 报错
    }
    
    function func(arg) {
      {
        let arg; // 不报错
      }
    }
    
  • let新增块级作用域

    • ES5只有全局作用域和函数作用域

    • ES5函数只能在顶层作用域和函数作用域内声明,不能在块级作用域内声明

      // ES5 情况一:非法
      if (true) {
        function f () {}
      }
      
      // ES5 情况二:非法
      try {
        function f () {}
      } catch (e) {
        // ...
      }
      
      // ES6
      if (true) {
        function f () {}
      }
      
    • 在块级作用域内,函数声明语句的行为类似于let,在块级作用域之外不可引用,对作用域之外并不会影响

      // 对于本例:
      function f() { console.log('I am outside!'); }
      (function () {  
        if (false) {   
         // 重复声明一次函数f    
          function f() { console.log('I am inside!'); }   
        }  
       f();
      }());
      
      // ES5实际运行代码:结果为:I am inside!
      function f() { console.log('I am outside!');  }
      (function () {  
        function f() { console.log('I am inside!'); }   
        if (false) {   
        }  
       f();
      }());
      
      // ES6实际运行代码:结果为:I am outside!
      function f() { console.log('I am outside!');  }
      (function () {  
       f();
      }());
      

const

声明常量,不可变指的是该常量指向的地址,而不是常量本身

  • const声明一个只读的常量,一旦声明,常量的值就不能改变

    const PI = 3.1415;
    PI // 3.1415
    
    PI = 3;
    // TypeError: Assignment to constant variable.
    
  • const一旦声明变量,就必须立即初始化,不能等到以后赋值

    const foo;
    // SyntaxError: Missing initializer in const declaration
    
  • 只在声明所在的块级作用域内有效

    if (true) {
      const MAX = 5;
    }
    
    MAX // Uncaught ReferenceError: MAX is not defined
    
  • const声明的常量也不存在变量提升

  • 存在暂时性死区

  • 只能先声明后使用

  • 不可重复声明

  • 对于复合类型的变量,变量名不指向数据,而是指向数据所在的地址。即const命令只是保证变量名指向的地址不变,而不是保证数据不变,所以使用const声明为常量必须小心。

    const foo = {};
    foo.prop = 123;
    foo.prop
    // 123
    foo = {}; // TypeError: "foo" is read-only
    

    上例中:常量foo存储的是一个地址,这个地址指向一个对象。所谓不可变的是这个地址,不能把foo指向另一个地址,但是该对象本身是可变的,可以为这个对象添加新属性等

    const a = [];
    a.push('Hello'); // 可执行
    a.length = 0;    // 可执行
    a = ['Dave'];    // 报错
    

    上例中:常量a是一个数组,这个数组本身是可写的,但是将另一个数组赋给a,就会报错,因为改变了a指向的地址

ES6其他声明变量的方法

共6中声明变量的方法:

  • ES5两种:var 和 function
  • ES6新增的:let 和 const
  • ES6其他:import 和 class