var是ES5中定义变量的关键字,声明的变量是全局作用域或函数作用域,并且具有提升的特性,也就是说可以在声明之前使用变量。
let和const是ES6中新增的关键字,声明的变量具有块级作用域,只在当前块内有效,不具有提升的特性。let声明的变量可以被重新赋值,而const声明的变量是一个常量,一旦赋值就不能再修改。
(1)作用域
用 var 声明的变量的作用域是它当前的执行上下文,即如果是在任何函数外面,则是全局执行上下文,如果在函数里面,则是当前函数执行上下文。换句话说,var 声明的变量的作用域只能是全局或者整个函数块的。
而 let和const 声明的变量的作用域则是它当前所处代码块,即它的作用域既可以是全局或者整个函数块,也可以是 if、while、switch等用{}
限定的代码块。
function varTest() {
var a = 1;
{
var a = 2; // 函数块中,同一个变量
console.log(a); // 2
}
console.log(a); // 2
}
function letTest() {
let a = 1;
{
let a = 2; // 代码块中,新的变量
console.log(a); // 2
}
console.log(a); // 1
}
function constTest() {
const a = 1;
{
const = 2; // 代码块中,新的变量
console.log(a); // 2
}
console.log(a); // 1
}
varTest();
letTest();
constTest();
从上述示例中可以看出,let 声明的变量的作用域可以比 var 声明的变量的作用域有更小的限定范围,更具灵活。
(2)重复声明
var 允许在同一作用域中重复声明,而 let ,const不允许在同一作用域中重复声明,否则将抛出异常。
代码块1:
switch(index) {
case 0:
consta = 1;
break;
default:
consta = 2; // SyntaxError: Identifier 'a' has already been declared
break;
}
代码块2:
switch(index) {
case 0:
let a = 1;
break;
default:
let a = 2; // SyntaxError: Identifier 'a' has already been declared
break;
}
代码块3:
//
var a = 1;
var a = 2;
console.log(a) // 2
function test() {
var a = 3;
var a = 4;
console.log(a) // 4
}
test()
(3)绑定全局对象
var 在全局环境声明变量,会在全局对象里新建一个属性,而 let,const 在全局环境声明变量,则不会在全局对象里新建一个属性。
var a = '你好'
let b = '你好'
const c = '你好'
console.log(this.a) // 你好
console.log(this.b) // undefined
console.log(this.c) // undefined
(4)变量提升与暂存死区
console.log(a); //暂时性死区,报错 Unexpected identifier 'Uncaught'
const b = 1;
console.log(b);
console.log(a); //暂时性死区,报错 Unexpected identifier 'Uncaught'
let b = 1;
console.log(b);
console.log(a); //undefined
var = 1;
console.log(a);
变量 a 用 var 声明存在变量提升,所以当脚本开始运行的时候,b 已经存在了,但是还没有赋值,所以会输出 undefined。
变量 b 用 let,const 声明不存在变量提升,在声明变量 a 之前,a 不存在,所以会报错。
const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。