var、let、const 之间的区别

1. var

  • var 声明的变量既是全局变量,也是顶层变量。注意:顶层对象在浏览器环境指的是 window 对象,在 Node 指的是 global 对象。
  • 使用 var 声明的变量存在变量提升的情况。
var a = 10;
console.log(window.a); // 10,a 也是顶层变量

在函数中使用 var 声明变量时,该变量是局部的:

var a = 20;
function change() {
  var a = 30;
}
change();
console.log(a); // 20

而如果在函数内不使用 var,该变量是全局的:

var a = 20;
function change() {
  a = 30;
}
change();
console.log(a); // 30

2. let

  • 无变量提升,块状作用域。
  • 只要块级作用域内存在 let 命令,这个区域就不再受外部影响。
var a = 123;
if (true) {
  a = 'abc'; // ReferenceError
  let a;
}
  • let 不允许在相同作用域中重复声明:
let a = 20;
let a = 30;
// Uncaught SyntaxError: Identifier 'a' has already been declared

3. 暂时性死区(TDZ)

使用 let、const、import、class、typeof 等关键字声明变量前,该变量都不可用。

原因:这些关键字声明的变量会产生块级作用域,如果变量在当前作用域中被创建之前创造出来,由于此时还未完成语法绑定,访问或使用就会产生暂时性死区。从变量创建到语法绑定之间的一段空间可以理解为暂时性死区。

4. const

  • 只读常量,一旦声明常量的值就不能改变。
  • const 一旦声明变量就必须立即初始化,不能等到以后赋值。
  • const 实际保证的不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不能改动(const 只能保证指针是固定的)。

补充:

  • 顶层声明的 var / function 是全局属性,可被 window 访问;let / const / class 则不是。
  • 在循环中 var 声明的变量会"泄漏"到函数作用域,let 则为每次迭代创建新的绑定(这是闭包经典题的根因)。
  • const 声明对象时,属性仍可增删改;如果需要冻结,使用 Object.freeze。

来源整理自:我的有道云笔记