Skip to content

ES6 之let 和 const #38

@wangjing013

Description

@wangjing013

在 ES6 之前通常定义变量的通过 var 关键字. 如下:

var a = 1;
var fn = function(){}
function test (){
   console.log(a); // undefined
   var a = 2;
}

在 ES6 之中引入 letconst, 为什么需要引入这两个关键字. 先来回顾下 var 相关的内容:

  • 全局声明的变量会添加 window
  "use strict"
  var a = 1;
  console.log(window.a); //=> 1

  var RegExp = "Hello";
  console.log(RegExp); //=> "Hello"
  console.log(window.RegExp); //=> "Hello"

带来的问题就是, 容易覆盖 window 上内置对象.

  • 允许重复声明(同一个作用域中)
  "use strict"
  var a = 1;
  var a = 2;
  console.log(a); //=> 2
  • 变量提升(Hosting)
  console.log(a); //=> undefined
  var a = 1;
  
  function test() {
     console.log(a); //=>  undefined
     var a = 2;
     console.log(a); //=> 2
  }
  • 不存在块级作用域
  {
    var a = 1;
  }
  console.log(a); //=> a
  
  for (var i =0; i < 5; i++){
    setTimeout(function(){
       console.log(i);
    })
  }
  // => 5 5 5 5 5

了解 var 基本概念后, 再来了解下 let 相关的.

  • 全局声明的变量不会添加 window
let a = 1;
console.log(a); //=> 1
console.log(window.a); //=> undefined

 let RegExp = "Hello";
 console.log(RegExp); //=> "Hello"
 console.log(window.RegExp); //=> ƒ RegExp() { [native code] }

只会形成遮蔽, 并不会覆盖其内置对象.

  • 不允许重复声明(同一个作用域中)
let a = 1;
let a = 1;
//=> Uncaught SyntaxError: Identifier 'a' has already been declared

这样避免被覆盖的问题, 减少程序产生莫名其妙的问题.

  • 不存在变量提升
  console.log(a); //=> Uncaught ReferenceError: a is not defined
  let a = 1;
  • 暂时性死区(temporal dead zone)
 function test() {
     console.log(a); //=>  Uncaught ReferenceError: Cannot access 'a' before initialization
     let a = 2;
     console.log(a); //=> 2
  }
 test();

TDZ 并不是ECMA的标准, 只是为了方便描述 letconst 不提升效果. JavaScript 引擎在扫码代码时, 发现变量是通过 var 声明的则提升变量到作用域顶部, 如果是通过 let or const 则会把变量放入到 TDZ 中, 当在声明之前访问则会报错.

  • 存在块级作用域
  {
    let  a = 1;
  }
  console.log(a); //=> Uncaught ReferenceError: a is not defined
  
  for (let i =0; i < 5; i++){
    setTimeout(function(){
       console.log(i);
    })
  }
  // => 0 1  2 3 4

let 中可以看到相比 var 带来的不同, 使代码变得更加健壮, 减少莫名其妙的问题.

了解完 varlet 之后, 再来了解下 const.

其实 letconst 几乎差不多, 区别.

  • 不允许重复赋值(声明的时必须赋值)
const a = 1;
a = 1; //=> Uncaught SyntaxError: Identifier 'a' has already been declared
  • for 循环
 for (const i =0; i < 5; i++){ 
    setTimeout(function(){
       console.log(i);
    })
  }
//=> Uncaught TypeError: Assignment to constant variable.

for infor of 中与 let 一致.

对比

描述 var let
Hosting
Block Scoped
re-declared
Brower Support 所有浏览器 现代浏览器
Compatibility 支持所有浏览器及JS运行时环境 需要借助类似 babel 转换成老版本, 从而才能支持所有浏览器

最佳实践

默认使用const, 只在确定需要修改变量值时使用 let , 这样可以在某种程度上实现代码的不可变, 从而防止某些错误的产生.

总结

  • letconst 为 JavaScript 引入块级作用域的概念
  • letconst 的特性大大提升产生错误的几率
    • 不会添加到 window 上
    • 不允许重复声明
    • 块级作用域
    • TDZ
    • 不允许重复赋值(const)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions