ES6中let、const与var的区别

233 阅读2分钟

var

  • 使用var声明的变量是全局变量,且在预编译环节会提升至顶部(变量提升)

    console.log(a); // -> undefined
    var a = 3;
    console.log(window.a); // -> 3
    
  • var可以重复声明,后面的会覆盖前面的

    var b = 1;
    var b = 2;
    console.log(b); // -> 2
    

let

  • let声明的变量不存在变量提升的机制,也就是没有声明就不可以调用(暂时性死区)。

    console.log(foo); // ReferenceError
    let foo = 2;
    
  • let声明的变量有了块级作用域的概念,{}就是一个块。ES6之前只有全局作用域和函数作用域,导致很多的场景不可理, 内部变量会覆盖外层同名变量,for循环的变量泄漏为全局变量。

    function test () {      
      let a = 'outer';
    
      if(true){        
        let a = 'inner';        
        console.log(a); // -> 'inner'      
      }
    
     console.log(a); // -> 'outer'
    }
    test();
    
    for(let i = 0; i < 3; i++){
      console.log(i); // -> 0 1 2
    }
    console.log(i); // ReferenceError: i is not defined
    

 注:在for循环这里有一个特别之处,在设置循环变量的时候相当于一个父级作用域,在循环体中是一个单独的子作用域,let 的本质就是形成一个块级作用域。

for(let i = 0; i < 3; i++){
   let i = 'a';
   console.log(i) // -> 会打印三次 'a'
}

for(let i = 0; i < 3; i++){
   i = 'a';
   console.log(i); // -> 只打印一次 'a'
}
  • let在同一作用域下不可以重复声明

    function fn () {      
      let a = 1;      
      let a = 2;    
    }
    // SyntaxError: Identifier 'a' has already been declared
    

const

  • const声明一个只读的常量,一旦声明,必须立即初始化且常量的值不会改变。

    const id = 33;
    id = 44; // 报错 TypeError: Assignment to constant variable.
    
  • 如果定义的是引用类型的值呢?

    const foo = {};
    foo = {name: "jerome", age: "22"};
    console.log(foo); // 报错
    
    foo.name = 'jerome';
    foo.age = '22';
    console.log(foo); // {name: "jerome", age: "22"}
    
  • 得出结论如果是引用类型的值 const 只会保证变量指向的内存地址不变,而不是变量的值不可改。

注:对象的值不可改(冻结对象)可以用 Object.freeze();

总结:

      const 与 let 一样不存在变量提升、具有块级作用域、存在暂时性死区、不允许重复声明。还有const 与 let 声明的变量不会挂载到顶层对象(window 浏览器环境)上。