var , let , const 的区别

271 阅读3分钟

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

总结

  1. var的声明范围是函数作用域,let/const的声明范围是块作用域
  2. var在同一作用域下可以重复声明同一个变量,let/const 不能
  3. var的声明会被提升到作用域顶端,let/const 没有变量提升
  4. 暂时性死区,let/const 在声明之前都不能以任何方式访问变量,会报错
  5. var在全局作用域下声明的变量会成为全局对象属性,let/const 不会
  6. const声明变量时候必须初始化
  7. const声明的变量不可以被修改(对于引用类型保证引用地址不变就可以)