var、let、const之间的区别
一、var
1、在ES5中,顶层对象的属性和全局变量是等价的,用var
声明的变量既是全局变量,也是顶层变量(顶层对象,在浏览器环境指的是window对象)。
var a = 10;
console.log(window.a); // 10
2、使用var
声明的变量存在变量提升的情况:
console.log(a); // undefined
var a = 20;
// 在编译阶段,编译器会将其变成以下执行
var a;
console.log(a);
a = 20;
3、使用var
,能对一个变量进行多次声明,后面声明的变量会覆盖前面的变量声明。
var a = 10;
var a = 20;
console.log(a); // 20
4、在函数中使用var
声明变量,此时该变量是局部的。
var a = 20;
function fun() {
var a = 30;
}
fun();
console.log(a); // 20
如果函数中没有使用var
声明,则该变量是全局变量。
var a = 20;
function fun() {
a = 30;
}
fun();
console.log(a); // 30
二、let
let
是ES6新增的命令,用来声明变量
。
用法类似于var
,但是let声明的变量,只在let
命令所在的代码块内有效。
{
let a = 20;
console.log(a); // ReferenceError: a is not defined
}
// 不存在变量提升
console.log(a); // ReferenceError: a is not defined
let a = 20;
这表示在声明它之前,变量a是不存在的,这时如果用到a,就会抛出一个错误。
只要块级作用域内存在let命令,这个区域就不再受外部影响。
var a = 30;
if(true) {
a = 'abc'; // ReferenceError: Cannot access 'a' before initialization
let a;
}
// 在使用let变量前,该变量都不可用,“暂时性死区”
let
不允许在相同作用域中重复声明。
let a = 20;
let a = 30;
// Uncaught SyntaxError: Identifier 'a' has already been declared
// 但如果是以下这种情况是不会报错的
let a = 20;
{
let a = 30; // 作用域不同
}
因此,我们不能在函数内部重新声明参数。
function fun(val) {
let val;
}
fun();
// SyntaxError: Identifier 'val' has already been declared
三、const
const声明一个只读的常量
,一旦声明,常量的值就不能改变。
const b = 30;
b = 60;
// TypeError: Assignment to constant variable.
const一旦声明变量,就必须立即初始化,不能留到以后赋值。
如果之前用var、let声明过变量,再使用const声明会报错。
var a = 10;
let a = 20;
const a = 40;
const实际上保证的不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
对于简单类型的数据,值久保存在变量指向的那个内存地址,因此等同于常量。
对于复杂类型的数据,变量保存的只是一个指向实际数据的指针,const
只能保证这个指针是固定的,并不能确保变量的结构不变。
const obj = {};
obj.val = 99;
console.log(obj.val); // 99
const obj = {};
obj.val = 99;
obj = {}
console.log(obj.val); // TypeError: Assignment to constant variable.
四、区别
变量声明
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined;
let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错。
// var
console.log(a) // undefined
var a = 10
// let
console.log(b) // Cannot access 'b' before initialization
let b = 10
// const
console.log(c) // Cannot access 'c' before initialization
const c = 10
暂时性死区
var
不存在暂时性死区,let
和const
存在暂时性死区,只有等到声明变量的那一行代码出现,才能获取和使用该变量。
块级作用域
var
不存在块级作用域;let
和const
存在块级作用域。
// var
{
var a = 20
}
console.log(a) // 20
// let
{
let b = 20
}
console.log(b) // Uncaught ReferenceError: b is not defined
// const
{
const c = 20
}
console.log(c) // Uncaught ReferenceError: c is not defined
重复声明
var允许重复声明,let和const在同一作用域不允许重复声明变量。
// var
var a = 10
var a = 20 // 20
// let
let b = 10
let b = 20 // Identifier 'b' has already been declared
// const
const c = 10
const c = 20 // Identifier 'c' has already been declared
修改声明的变量
var和let变量声明后可以修改,const声明的是一个只读常量,一旦声明不能改变。
// var
var a = 10
a = 20
console.log(a) // 20
//let
let b = 10
b = 20
console.log(b) // 20
// const
const c = 10
c = 20
console.log(c) // Uncaught TypeError: Assignment to constant variable
能用const
尽量用const
,其他情况大多使用let
,避免使用var
。