ECMAScript有三个关键字可以声明变量:var、let、const。var ECMAScript的所用版本中都可以使用,let和const只能在ECMAScript6及之后的版本中只用,const用于声明常量。
1.变量提升
var 声明变量可以提升;
let/const 声明变量一定要在声明后再使用,否则会报错。使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
console.log(name) //undefined
var name = "Kelly";
console.log(age) //在初始化之前无法访问“name”
let age = 10;
console.log(message) //在初始化之前无法访问“message”
const message = "hello";
使用var关键字 以上代码不会报错,因为var关键字声明的变量会自动提升到函数作用域顶部,等价于如下代码:
var name;
console.log(name) //undefined
name = "Kelly";
2.重复声明
var 可以重复声明;
let/const 不可以可以重复声明
var name = "Kelly";
var name = "William";
console.log(name) //William
let age = 10;
let age = 20;
console.log(age) //标识符“age”已经声明
const message = "hello";
const message = "hi";
console.log(message) //标识符“message”已经声明
3.作用域
var 函数级作用域;
let/const 块级作用域 在let之前,for循环定义的迭代变量会渗透到循环体外部,改为使用let,这个问题就消失了,因为迭代变量的作用域仅限于for循坏快内部:
for (var k = 0; k < 5; ++k) {
setTimeout(() => console.log(k),0) //5 5 5 5 5
}
console.log(k) //5
for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i),0) //0 1 2 3 4
}
console.log(i) //i is not defined
//虽然let和const变量相似,但是不能用const来声明迭代变量(因为迭代变量会自增)
for (const i = 0; i < 5; ++i) {
console.log(i) //Assignment to constant variable.
}
4.全局变量vs全局对象的属性
ES6 中做了严格的区分,使用 var 和 function 声明的全局变量依旧作为全局对象的属性,使用 let, const 命令声明的全局变量不属于全局对象的属性。
var name = "Kelly";
console.log(window.name); //Kelly
console.log(this.name) //Kelly
let age = 20;
console.log(window.age); // undefined
console.log(this.age) // undefined
5.值修改
var和let的值可以修改;
const 定义常量 值不能修改
var name = "Kelly";
name = "William";
console.log(name) //William
let age = 10;
age = 20;
console.log(age) //20
const message = "hello";
message = "hi";
console.log(message) //Assignment to constant variable.
补充
const声明的限制只适用指向的变量的引用,如果const变量引用的是一个对象,那么修改对象内部的属性是可以的。;
const person = {};
person.name = "Kelly";
console.log(person.name) //Kelly
//如果想让整个对象都不能修改 使用object.freeze()
const person1 = Object.freeze({});
person1.name = "Kelly";
console.log(person1.name) //undefined