参考
《JS 高级程序设计》
在 JS 中有三种声明变量的关键字,分别是 var,let 和 const,其中 let 和 const 都是在 ES6 中新增的关键字。
var
作用域
- var 在全局声明的变量或称为 window 对象的属性
var name = 'Matt';
console.log(window.name); // 'Matt'
- var 的作用域范围被限制在一个函数中,也就是说,任何包裹 var 的情况中,只有函数才会限制 var 的作用域
function test() {
var message = "hi"; // 局部变量
}
test();
console.log(message); // 出错!
可以看到上面的函数作用域中,一旦 var 的变量超过了这个函数范围,则无效。但是如果包裹 var 的不是函数,而是其他方式则不会出错。
if(true){
var a = 10;
}
console.log(a); // 10
变量提升
凡是 var 声明的变量均会自动提升到函数作用域的顶部
function foo() {
console.log(age); var age = 26;
}
像上面的方式是正确的,因为实际上 ES 会把它解析成下面的方式,当然打印出来的是 undefined,但是语法是正确的
function foo() {
var age; console.log(age); age = 26;
}
let
- let 声明的范围是块作用域,什么是块呢,就是 { } 中间包裹的内容
- 和 var 相比,let 不具备变量提升的能力
- 我们知道 var 只受到函数作用域的限制,并不受到其他作用域的限制
// 可以看到 var 超出了这个范围依然可以正确执行
if (true) {
var name = 'Matt'; console.log(name); // Matt
}
console.log(name); // Matt
但是 let 是受到 { } 的限制,超出这个范围就会报错
if (true) {
let age = 26; console.log(age); // 26
}
console.log(age); // ReferenceError: age 没有定义
【注】let 和 var 不能声明相同的变量
let name = 'lili';
var name = 'zhangsan'; // Uncaught SyntaxError: Identifier 'name' has already been declared
- let 在全局声明的变量不会成为 window 的属性,但是是一个全局变量
let age = 26;
console.log(window.age); // undefined
let 的应用
- for 循环中的 let。let 的出现,成功解决了 var 时代,迭代变量溢出到循环体外的问题
for (var i = 0; i < 5; ++i) {
setTimeout(()=>console.log(i),0);
}
// 都是输出 5,而不是 0,1,2,3,4for (let i = 0; i < 5; ++i) {
setTimeout(()=>console.log(i),0);
}
// 正常输出 0,1,2,3,4
const
- const 的表现与 let 相同,区别在于 const 是声明一个常量,即只能对一个量声明一次(声明的时候必须赋值),以后就固定了,下一次想要修改就会报错
const age = 26;
age = 36; // 报错
- 对于对象来说,const 只能限制对象的引用,而不能限制对象内部的内容
const person = {
};
person.name = 'Matt'; // ok