彻底搞懂JS声明变量(var、let、const)

8 阅读3分钟

变量在编程语言中占据着非常重要的地位。在JavaScript这门编程语言中,总共有三种声明变量的方式,分别是:var、let、const,其中let和const只能在es6及更晚的版本中使用。

var关键字

声明作用域

如果你用var声明了一个变量想访问它的话,只能在该变量所在的函数中访问它,即函数作用域。函数嵌套的情况下,内部函数可以访问外部函数声明的变量。如果没有在函数中声明的话,var声明的变量就会挂载到window对象下

var a = 1;
function fun1() {
    var b = 2;
    function fun2() {
        console.log(a, b); // 1 2
    }
    console.log(b); // 2
    fun2();
}
fun1();
console.log(a, window.a); // 1 1
console.log(b); // ReferenceError: b is not defined

第5行代码中,当打印a,b变量的值时,fun2函数中并没有这两个变量,会向外部进行查找。第11行代码中,因为变量a的声明不在任何函数中,所以挂载到了window对象下。第12行代码中,b并没有声明,也不能够向内部的函数进行查找。

声明提升

请看以下代码:

console.log(a); // undefined
var a = 1;
console.log(a); // 1

你肯定会好奇第1行的为什么会打印undefined?因为上述代码会转换为以下代码:

var a;
console.log(a); // undefined
a = 1;
console.log(a); // 1

这就是var关键字的声明提升,不管你是在哪里用var声明的变量,声明语句都会被提升到代码的最前面,赋值语句还是在原地不动。

let关键字

块级作用域

let声明的变量和var非常相似,最明显的区别是let声明的变量属于块级作用域。什么是块级作用域呢?用一对大括号括起来的代码就属于同一个块级作用域。

{
    let a = 1;
    console.log(a); // 1
}
console.log(a); // Uncaught ReferenceError: a is not defined

第五行代码访问不到块级作用域中声明的变量a。如果换成var的话,第五行就会输出1。

注意:let声明的变量不会进行声明提升,也不会挂载到window对象下。

const关键字

const声明的变量和let几乎一模一样,唯一的区别就是const声明的变量是不能进行更改的,并且在声明的时候必须要进行赋值,且赋值后不能重新赋值。但对象里的属性可以重新进行赋值。

const a = 1;
const obj = {
    b: 2
};
//a = 2; //Uncaught TypeError: Assignment to constant variable.
obj.b = 3;
console.log(a, obj); // 1 {b: 3}

代码第五行尝试给a重新赋值时,整个代码会报错,而第六行却可以将对象里的属性重新赋值。这是因为obj这个变量存储的是一个地址值,指向{b:2}这个对象,当你变更属性b的值时,obj的地址值并不会发生改变。

总结

优先使用const,其次let,最后是var。因为var的声明提升会混淆变量的声明位置,并且容易破坏window对象,降低代码的可读性。对于一些明确不会改变的变量,用const声明有助于提升代码性能。如果确实后期需要改变这个值的话,用let声明能够更好的确定作用域,并且提升代码质量。