变量在编程语言中占据着非常重要的地位。在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声明能够更好的确定作用域,并且提升代码质量。