前言
在ES6之前,JavaScript中声明变量就只有通过 var
关键字,函数声明是通过 function 关键字,而在ES6之后,声明的方式有 var 、 let 、 const 、 function 、 class ,本文主要讨论 var
、 let
和 const
之间的区别。
var
1.使用var
声明一个变量,这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域。
2.var
定义的变量可以修改,如果不初始化会输出undefined
,不会报错。
var a; //不会报错
console.log(a); // undefined
3.存在变量提升,注意:只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。
function foo() {
console.log( a ); // undefined,并没有报错
var a = 2;
}
let
1.let
声明的变量具有块作用域的特征。
function foo() {
let a = 1;
}
console.log(a); // Uncaught ReferenceError: a is not defined
2.同var
一样,let
定义的变量值可以修改,如果不初始化会输出undefined
,但是在同一个块级作用域,不能重复声明变量。
function foo() {
let a = 1;
let a = 2;//Uncaught SyntaxError: Identifier 'a' has already been declared
}
3.let
声明的变量不存在变量提升,换一种说法,就是 let
声明存在暂时性死区(TDZ)。
TDZ 指的是由于代码中的变量还没有初始化而不能被引用的情况,最直观的例子是ES6 规范中的let 块作用域:
console.log(a);//Uncaught ReferenceError: a is not defined
let a = 2;
对未声明变量使用typeof 不会产生错误,但在TDZ 中却会报错:
function foo() {
typeof a; // undefined
typeof b; // ReferenceError! (TDZ)
let b;
}
const
除了let
以外,ES6 还引入了const
,同样可以用来创建块作用域变量,但其值是固定的(常量)。之后任何试图修改值的操作都会引起错误。
function foo() {
var a = 2;
const b = 3; // 包含在if 中的块作用域常量
a = 3; // 正常!
b = 4; // 错误!
}
console.log( a ); // 3
console.log( b ); // ReferenceError!
小结
1.var
定义的变量属于函数作用域,let
和 const
定义的变量属于块级作用域。
2.var
存在变量提升现象, let
和 const
没有。
3.var
变量可以重复声明,在同一个块级作用域,let
变量不能重新声明,const
变量不能修改。
参考:《你不知道的JavaScript(上卷)》