var、let、const的区别

186 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

注意: 本文的示例代码结果都是在node环境下运行的结果,node版本:V12.19.0。

关于var、let、const这三者的区别,我们先来说说var和let的区别,最后再说const。

1. 作用域不同

let关键字声明:

如果是在代码块中声明的变量,那么只能在代码块中访问在代码块外面是无法访问该变量的,这也就是ES6为我们带来的块级作用域

var关键字声明:

如果在代码块中声明的变量,那么在代码块外面依然可以访问该变量,也就是说块级作用域对于var声明的变量是没有限制的。

能够限制var关键字声明变量的作用域是函数作用域,如果var在函数内部声明变量,那么它会作为局部变量存在,函数外部是无法访问的。当然,这条规则也适用于let关键字声明的变量

示例代码如下

function test(flag) {
     if (flag) {
         var name = '娜个小部';
     }
     // 使用var关键字在代码块中声明的变量,在代码块外面依然可以访问。
     console.log(name); // 娜个小部
}

test(true);

// 函数体内部使用var关键字声明的变量,在函数外部无法访问
console.log(name) // ReferenceError: name is not defined

/**************不怎么华丽的分割线***************/

function test(flag) {
     if (flag) {
         let name = '娜个小部';
     }
     // 使用let关键字在代码块中声明的变量,在代码块外面是无法访问的。
     console.log(name); // ReferenceError: name is not defined
}

test(true);

// 函数体内部使用let关键字声明的变量,在函数外部无法访问
console.log(name); // ReferenceError: name is not defined

2. 变量提升

使用var关键字声明的变量存在变量提升,而使用let关键字声明的变量不存在变量提升的问题。

这里解释下什么叫做提升(hoist):就是将var关键字声明的变量全部拉到当前作用域的最顶部。

示例代码如下

function test(flag) {
     var name; // 先定义
     if (flag) {
        name = '娜个小部'; // 重新赋值
     }
     console.log(name); // 娜个小部
}

test(true); 

3. 冗余声明

这个很好理解,var关键字声明的变量可以重复声明,而let关键字声明的变量不可以重复声明。

示例代码如下

// var关键字声明的变量可以重复声明
function test() {
    var age = 18;
    var age = 28;
    var age = 38;
    console.log(age) // 38
}

test();

// let关键字声明的变量不可以重复声明, 如果重复声明会报错
function test() {
    let age = 18;
    let age = 28; // SyntaxError: Identifier 'age' has already been declared
    let age = 38;
}

test();

4. 暂时性死区

由于let关键字声明的变量不会在作用域中被提升,所以在解析代码时,JavaScript引擎也会注意出现在块后面的let声明,在此之前不能以任何方式来引用未声明的变量。在let声明之前的执行瞬间被称为暂时性死区(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError。

示例代码如下

conole.log(name); // 报错

// conole.log(typeof name); // 报错

let name = '娜个小部';

5. 全局声明

var关键字声明的变量,在全局作用域中会作为window对象的一个属性存在。 let关键字声明的变量则不会作为window对象的属性存在,不过let声明的全局变量依然是在当前页面的声明周期内存续的。

注意下面的示例代码是在浏览器环境下运行的,node环境全局对象为global, var 和let 二者声明的变量都不会作为global属性存在

var name1 = '娜个小部';
let name2 = '娜个小部呀!';

console.log(window.name1); // 娜个小部
console.log(window.name2); // 娜个小部呀

6. 条件声明

var关键字声明的变量由于存在变量提升,所以JavaScript引擎会自动将多余的声明在作用域顶部合并为一个声明。而let关键字声明的变量的作用域是块,因此它不可能检查前面是否已经使用let声明过同名变量了,即let关键字无法使用条件声明模式。

示例代码如下

if (typeof name1 === 'undefined') {
    let name1;
}
// 上面代码 如果name不存在,则声明一个name,因为name是在块中声明的,所以下面这句代码就相当于声明了个全局变量。
name1 = '娜个小部';

console.log(window.name1); // 娜个小部

let与const的区别

其实let与const非常相似,我列举一下,大家可以感受下:

  1. 都不能变量提升
  2. 作用域都是块级作用域
  3. 都不能重复声明

不同点是let声明的是变量,而const声明的是常量,声明后不能修改,如果修改会导致运行错误。

如果const声明的常量是一个引用类型,那么修改这个常量里面的属性值不会导致运行错误。

for(const i = 0; i < 10; i++) {} // 报错了,因为i是一个迭代变量,会自增;

const params = {
    name: '娜个小部';
    age: 18
};

params.name = '猜猜我是谁'; // 不会报错

本文已结束,拜拜喽!