详解var let const 的区别

77 阅读3分钟

1.作用域

  • var 没有块级作用域,而 let 声明的范围是块作用域; 一对大括号 就是 一个块级作用域
if (true) {
    var msg = "hello";
    console.log(msg); // hello
}
console.log(msg); // hello


if (true) {
    let msg = "hello";
    console.log(msg); // hello
}
console.log(msg); // error: msg is not defined

  • let 不允许同一个块作用域中出现冗余声明:
if (true) {
    // error: 无法重新声明块范围变量“msg”
    let msg;
    let msg;
}
  • JS 引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,这是因为同一个块中没有重复声明:
let msg = 666;
console.log(msg); // 666
if (true) {
    let msg = '啊哈哈';
    console.log(msg); // 啊哈哈
}
  • var 和 let 声明的并不是不同类型的变量,它们只是指出变量在相关作用域如何存在,所以对声明冗余报错不会因混用 var 和 let 而受影响:
// error
var msg;
let msg;

// error
let msg;
var msg;

2.变量提升

//用var命名的变量有变量提升
console.log(num1);  // undefined
var num1 = 10;
// 以上代码运行时,相当于下面的写法
​
var num2;  // 声明提升到作用域最顶端
console.log(num2);  // undefined
num2 = 10;
/*****************************************/
//用 let 或 const 命名的变量没有变量提升
console.log(num3); // Cannot access 'num3' before initialization
let num3 = 10;
​
console.log(num4); // Cannot access 'num3' before initialization
const num4 = 10;

3.暂时性死区

  • 在代码块内,使用let和const命令声明变量之前,该变量都是不可用的,叫暂时性死区

var tmp = 123; // 声明
if (true) {
  tmp = 'abc'; // 报错 因为本区域有tmp声明变量
  let tmp; // 绑定if这个块级的作用域 不能出现tmp变量
}
  • 暂时性死区和不能变量提升的意义在于: 为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

4.重复声明同名变量 和 重新赋值

//var 关键字可以声明同名变量,实际第二次声明是对第一次声明的变量重新赋值
var num1 = 10;
var num1 = 20;
console.log(num1);  // 20
​
//let 和const 关键字不能重复声明同名变量,即使之前是用var声明的也会报错
var num2 = 10;
let num2 = 20;  // Uncaught SyntaxError: Identifier 'num2' has already been declared
​
//let 和 var 在声明变量时,可以不用初始化
let num3;
console.log(num3);  // undefined
var num4;
console.log(num4);  // undefined
​
//const 声明常量时必须初始化,因为 `const` 关键字声明的是常量,声明后不能再赋值
const num5;  // Uncaught SyntaxError: Missing initializer in const declaration
//let 声明的变量可以重新赋值
let num1 = 10;
num1 = 20;
console.log(num1);  // 20
//const 只能在声明时赋值,之后不能再重新赋值
const num2 = 10;
num2 = 20;  // Uncaught TypeError: Assignment to constant variable.

5.var全局变量变成windows对象

var a = 666;
console.log(window.a); // 666

let b = 666;
console.log(window.b); // undefined

const c = 666;
console.log(window.c); // undefined

6.总结

  1. var 声明的范围是函数作用域,let 和 const 声明的范围是块作用域
  2. var 声明的变量会被提升到函数作用域的顶部,let 和 const 声明的变量不存在提升,且具有暂时性死区特征
  3. var 允许在同一个作用域中重复声明同一个变量,let 和 const 不允许
  4. const 的行为与 let 基本相同,唯一 一个重要的区别是,使用 const 声明的变量必须进行初始化,且不能被修改
  5. 在全局作用域中使用 var 声明的变量会成为 window 对象的属性,let 和 const 声明的变量则不会