var 是ES6之前用来声明变量的关键字,而let和const是ES6之后的版本出现的。let和const是为了解决var带来的得怪异行为。
var 声明
var声明的变量存在变量提升(hoist)
1 2 3 4 5
functiontest() { console.log(a) var a = 10 } test() //undefined
var声明的变量会先将变量a提升到作用域的顶部(在这里是test函数作用域),并初始化为undefined,然后等到执行var a = 10 才真正进行变量的赋值,其实现过程相当于
1 2 3 4 5 6
functiontest() { var a = undefined//变量提升到作用域顶部,并初始化为undefined console.log(a) a = 10 } test() //undefined
如果在函数内部声明的变量没有加关键字,则声明的变量会被创建在全局作用域
1 2 3 4 5 6 7
functiontest() { var a = 10; b = 'no var' } test() //undefined console.log(a) //报错 ReferenceError: a is not defined console.log(b) //正常输出 no var
反复多次使用var声明同一个变量也没有问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
functionfoo() { var age = 16; var age = 26; var age = 36; console.log(age); } foo(); // 36 //引擎会将所有声明的变量提升,合并为一个声明,相当于 functionfoo() { var age = undefined age = 16; age = 26; age = 36; console.log(age); }
let 和 const 声明
let 和 const 声明的范围是块作用域,而var 声明的范围是函数作用域。与let不同,const在声明时必须初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//var函数作用域 if (true) { var a = '函数作用域' console.log(a) //函数作用域 } console.log(a) //函数作用域
//let和const块作用域 if (true) { let a = 'let 块作用域' const b = 'const 块作用域' console.log(a) //let 块作用域 console.log(b) //const 块作用域 } console.log(a) //报错 ReferenceError: a is not defined console.log(b) //报错 ReferenceError: b is not defined
块作用域是函数作用域的子集,因此适用于var的作用域限制同样也适用于let
与var声明不同,let和const不允许同一个块作用域出现冗余声明
1 2 3 4 5
var name; var name;
let age; let age; //报错 SyntaxError: Identifier 'age' has already been declared
但是对于在不同作用域中使用let和const声明是允许的
1 2 3 4
let name = 'name'; if(true) { let name = 'another name'; //不会报错,且两者是不同的 }
在同一个作用域中,混合使用let和var声明同一个变量也是不允许的
let和const声明的变量不存在变量提升
1 2 3 4 5 6 7
console.log(a); //报错 ReferenceError: a is not defined console.log(b); //报错 ReferenceError: Cannot access 'b' before initialization