var, let, const 都是js中用来声明变量的关键字,let和const是ES6中新增的语法,我们就先来看看他们各自的一些特性。
var 声明
1. 声明范围
var的声明范围是函数作用域
2. 同一个变量可以重复声明
var age = 1;
var age = 2;
3. 声明但未初始化,会保存一个特殊值undefined
var name;
console.log(name) // undefined
4. 声明提升,提升到函数作用域的顶部
function test(){
console.log(name) // undefined
var name = 'abc'
}
test()
// 引擎编译时
function test(){
var name;
console.log(name)
name = 'abc'
}
5. 在全局环境下声明会成为全局对象的属性
// 当前是window 的全局环境
var name = 'abc'
window.name // 'abc'
let 声明
1. 声明范围
let 的声明范围是块作用域,就是 { } 中。
// 使用var中
if(true){
var name = "abc"
}
console.log(name) // "abc"
// 使用let
if(true){
let name = 'abc'
}
console.log(name) // Uncaught ReferenceError: name is not defined
name 变量无法在if外部引用,是因为let声明的变量的作用域仅限于块的内部,块作用域是函数作用域的子集,所以适用于var的作用域限制也适用于let
2. 无法在同一个块作用域下重复声明同一个变量
{
let name = 'abc'
let name = 'bcd'
var name = 'bcd'
// Uncaught SyntaxError: Identifier 'name' has already been declared
}
3. 无法提升
let和var的最大区别之一就是不能提升变量到作用域顶端,
{
console.log(name)
let name = "abc"
}
// Uncaught ReferenceError: name is not defined
4. 暂时性死区
暂时性死区, let 声明之前不能以任何方式来访问变量,在这之前执行的都会被称为暂时性死区
var name = 'abc'
if(true) {
name = 'ccc'
let name;
}
// Uncaught ReferenceError: name is not defined
// 这就是暂时性死区,在if的块作用域下已经用let声明了变量,在这之前都是不能访问变量的,就相当于在这个块里面将这个变量名锁定住了,只能在声明后才能访问
5. 声明但未初始化,会保存一个特殊值undefined
let name
console.log(name) // undefined
6. 在全局环境下声明,不会成为全局对象的属性
let name = 'abc'
window.name // undefined
const 声明
const声明规则基本上和let相同,区别在于const声明时候必须初始化,而且修改变量时会发生错误。(如果变量是原始型数据,修改就会报错。如果是引用型数据,变量是一个内存地址,只要保证地址不变就不会报错)
// 不能用const 来声明i,
// JavaScript 引擎会为 for 循环中的 let 声明分别创建独立的变量实例,
// 但是因为迭代变量会自增,const变量不能被修改,所以这里只能用let来声明,不能红const声明
for (const i = 0; i < 5; i++){}
// const 可以用于声明不能被改变的for 循环变量, for-in 和 for-of 很适用
for (const key in {a: 1, b: 2}) {
console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
console.log(value);
}
// 1, 2, 3, 4, 5
为什么需要块级作用域?
1. 为了防止变量覆盖
2. 避免变量污染,泄露为全局变量
// 循环完成后 全局对象中就多了一个i属性
for (var i = 0; i < 5; i++){}
console.log(i) // 5
// 使用let
for (let i = 0; i < 5; i++){}
console.log(i) // Uncaught ReferenceError: i is not defined
总结
- var的声明范围是函数作用域,let/const的声明范围是块作用域
- var在同一作用域下可以重复声明同一个变量,let/const 不能
- var的声明会被提升到作用域顶端,let/const 没有变量提升
- 暂时性死区,let/const 在声明之前都不能以任何方式访问变量,会报错
- var在全局作用域下声明的变量会成为全局对象属性,let/const 不会
- const声明变量时候必须初始化
- const声明的变量不可以被修改(对于引用类型保证引用地址不变就可以)