JavaScript:let、const、var三者区别

126 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

前言

let const var有什么区别?什么是块级作用域

基础概念

  • varletconst 是用来声明变量的三种方式,letconstES6 推出的声明变量方式;
  • ES6 之前的作用域有:全局作用域函数作用域ES6 新增了 块级作用域块级作用域 由一对大括号 { } 包裹。

区别

由于 letconst 特性相似,在文章结尾会对二者细节上的区别进行记录,这里只比较 letvar 的区别,

  1. var 没有块级作用域概念,let
  // Global Scope
  {
    // Block Scope
    var a = 10;
    let b = 20;
  }
  console.log(a); // 10
  console.log(b); // ReferenceError: b is not defined

Global Scope(全局作用域)中访问Block Scope(块级作用域)中var定义的变量a,输出结果为10,访问let定义的变量b则会报错:ReferenceError: b is not defined

  1. 同一作用域中,var 允许重复声明,let 则不行
  //Global Scope
  var a = 10;
  var a = 20;
  console.log(a);  //20
  
  let b = 30;
  let b = 40;
  console.log(b);  //SyntaxError: Identifier 'b' has already been declared
  1. 全局作用域使用 var 声明的变量会挂载到 window 对象上,let 则不会
  //Global Scope
  var a = 10;
  console.log(window.a);  //10
  let b = 20;
  console.log(window.b);  //undefined
  1. var 存在变量提升,let不存在变量提升
  console.log(a); // undefined
  var a = 'global a';
  function localScope() {
    console.log(a); // global a
    console.log(b); // ReferenceError: Cannot access 'b' before initialization
    let b = 'local b';
  }
  localScope();
  • Global Scope 中访问 var 关键字定义变量 a,得到结果为undefined
  • Local Scope 中访问 var 关键字定义变量 a 得到的结果也是 Global a,说明 Local Scope 中读取变量是按照作用域的层级依次往上找的,即:Local Scope 中没有定义变量 a,则读取Global Scope 中的变量 a
  • Local Scope 中访问 let 关键字定义的变量 b,程序报错:ReferenceError: Cannot access 'b' before initialization注意:这里错误信息指的是,不能在初始化之前访问变量b,而不是b is not defined
  1. let 声明的变量存在 暂时性死区(Temporal Dead Zone)

造成ReferenceError: Cannot access 'b' before initialization的原因是 let 声明的变量 b存在 暂时性死区

什么是暂时性死区

The variables are created when their containing Lexical Environment is instantiated but may not be accessed inany way until the variable’s LexicalBinding is evaluated. --- ES6标准第13章

即:当在新的作用域进行实例化时,在此作用域中用 let/const 声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在程序运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

简单来说就是,ES6规定了letconst 命令会使区块形成封闭的作用域。如果在声明前访问变量,就会报错。

const 关键字

const 关键字特性和 let 一致,区别在于:

  • 声明变量时就必须赋值,且后续不可更改
  • 后续不可更改指的是:变量指向的内存地址不可以修改
const a; // SyntaxError: Missing initializer in const declaration
const b = 10;
b = 5; // TypeError: Assignment to constant variable.
const c = {
  d: 1,
  e: 2
}
c.d = 3
console.log(c); // { d: 3, e: 2 }

总结

  • var 关键字
  1. 没有块级作用域的概念,只有全局作用域、函数作用域的概念;
  2. 同一作用域中允许重复声明
  3. 全局作用域使用声明的变量会挂载到 window 对象上
  4. 存在变量提升
  • let 关键字
  1. 存在块级作用域的概念
  2. 同一作用域中不允许重复声明
  3. 不存在变量提升,且具有暂时性死区
  • const 关键字 和 let 差别:声明变量时必须赋值,且其指向的内存地址在后续不可更改