var、let、const 的区别
trycoding.fun

var、let、const 的区别

变量提升、暂时性死区、块级作用域的对比

问题

说明 varletconst 三种变量声明方式的区别。

解答

作用域

// var 是函数作用域
function varScope() {
  if (true) {
    var x = 1;
  }
  console.log(x); // 1,可以访问
}

// let 和 const 是块级作用域
function letScope() {
  if (true) {
    let y = 1;
    const z = 2;
  }
  console.log(y); // ReferenceError: y is not defined
}

变量提升

// var 会提升,初始化为 undefined
console.log(a); // undefined
var a = 1;

// 等价于:
// var a;
// console.log(a);
// a = 1;

// let 和 const 也会提升,但存在暂时性死区
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 2;

暂时性死区(TDZ)

let x = 'outer';

function test() {
  // 从块开始到声明之前,x 处于暂时性死区
  console.log(x); // ReferenceError
  let x = 'inner';
}

// typeof 也不安全
console.log(typeof undeclaredVar); // undefined
console.log(typeof tdzVar); // ReferenceError
let tdzVar = 1;

重复声明

// var 允许重复声明
var a = 1;
var a = 2; // OK

// let 和 const 不允许
let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared

重新赋值

var a = 1;
a = 2; // OK

let b = 1;
b = 2; // OK

const c = 1;
c = 2; // TypeError: Assignment to constant variable

// const 声明的对象,属性可以修改
const obj = { name: 'Tom' };
obj.name = 'Jerry'; // OK
obj = {}; // TypeError

全局对象属性

var globalVar = 'var';
let globalLet = 'let';

console.log(window.globalVar); // 'var'
console.log(window.globalLet); // undefined

对比表格

特性varletconst
作用域函数块级块级
变量提升是(初始化为 undefined)是(TDZ)是(TDZ)
重复声明允许不允许不允许
重新赋值允许允许不允许
全局对象属性

关键点

  • var 是函数作用域,letconst 是块级作用域
  • 三者都有变量提升,但 letconst 存在暂时性死区(TDZ)
  • const 声明时必须初始化,且不能重新赋值,但对象属性可修改
  • 全局作用域下,var 声明的变量会成为 window 属性
  • 优先使用 const,需要重新赋值时用 let,避免使用 var