-
var、let、const都是用于声明变量的关键字,var在ECMAScript的所有版本中都可以使用;let和const只能在ES6及更晚的版本中使用。
-
是否存在变量提升:var存在变量提升;let、const不存在变量提升,即变量只能在声明之后使用,否则会报错。
function foo () {
console.log(age);
var age = 26;
}
foo(); // undefined
等价于:
function foo () {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
变量提升:把所有的变量声明都拉到函数作用域的顶部,变量可以在声明之前使用,值为undefined。
- 是否存在块级作用域:var声明的范围是函数作用域;let、const声明的范围是块级作用域。
if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
if (true) {
let name = 'Matt';
console.log(name); // Matt
}
console.log(name); // ReferenceError: name没有定义
块级作用域的作用:
- 解决了内层变量可能覆盖外层变量的问题。
- 解决了用来计数的循环变量泄露为全局变量的问题。
- 是否存在暂时性死区(temporal dead zone, TDZ):var不存在暂时性死区,let、const存在暂时性死区。
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp);// 123
}
暂时性死区:ES6规定,只要块级作用域中存在let或者const命令,它所声明的变量就绑定这个区域,不在受外部的影响,形成了封闭作用域,这个区域被称作暂时性死区,凡是在声明之前使用这些变量就会报错。
-
是否可以重复声明:var声明变量时可以重复声明,后声明的变量会覆盖之前的变量;let、const不允许重复声明。
-
声明变量时是否必须同时初始化变量:const声明变量时必须同时初始化变量;var、let声明变量时可以不要同时初始化变量。
-
声明的变量是否可以重新赋值:const声明的变量不可以重新赋值;var、let声明的变量可以重新赋值。
-
是否可以更改指针指向:const声明的变量不可以更改指针指向;var、let声明的变量可以更改指针指向。
-
是否会成为全局变量的属性:var声明的变量会成为全局变量的属性;let、const声明的变量不会成为全局变量的属性。