[JavaScript]搞清var、let与const

139 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 12 天,点击查看活动详情

声明变量

JavaScript中的变量是松散类型的,也就是说一个变量可以保存任何类型的数据,每个变量都只是一个用于保存任意值的命名占位符。
JavaScript中可以声明变量的有3个关键字:varletconst。其中letconst是从ECMAScript6中出现并使用的。

var、let和const异同点

1、相同点

var、let、const都是在JavaScript中定义变量的关键字

2、不同点

1、作用域

  • var是函数作用域,letconst都属于块级作用域

    function test() {
        {
            var hello = "你好!";
            let hello2 = "你好2!"
        }
        
        console.log(hello); //你好!
        console.log(hello2); // ReferenceError: hello2 is not defined
    }
    test()
    
  • 什么是块级作用域? 参考:JavaScript作用域汇总

2、变量提升

var有变量提升,let 没有变量提升的概念。
变量提升说的是,通过这个关键字声明的变量会自动提升到函数作用域顶部;

function test() {
    console.log(age)
    var age = 25;
}
test() // undefined

当定义一个变量,没有初始化(定义变量并赋值)的时候,这个变量默认保存的值为undefined

let 没有变量提升的概念,会报错!!!

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

function test() {
    console.log(age)
    let age = 25;
}
test() // ReferenceError: Cannot access 'age' before initialization

在变量声明之前是访问不到的,因为存在暂时性死区,暂时性死区在ECMAScript规范中没用明确命名,但通常用它来描述let/const声明的变量为什么在声明处之前不能被访问到。

3、重复声明

在同一作用域下,可以使用var多次声明同一个变量

function test() {
    var age = 16;
    console.log(age);
    var age = 26;
    var age = 36;
    console.log(age);
}
test(); // 16,36

let不允许同一个块级作用域下冗余声明, 就算var与let混用也不可以;
有小伙伴儿可能会疑惑,为什么var可以多次声明同一个变量,而let不行?

首先,这个问题根本就不用去纠结,没啥营养,当作规定理解也可;
其次,var声明变量,可以不断重复定义,没有任何限制的感觉很爽,但也会带来一些麻烦,真正开发中,多人协作,甚至都交过好几代人的手了,很容易误修改了不该修改的东西。let弥补了var的不足。

最后再强调一下,var,let混用也不能重复定义一个变量,因为这俩关键字只是指出这个变量的作用域是怎么存在的,而不是定义不同的变量。而let只要是同一个作用域下,就不可重复声明变量,不管是用哪个关键字定义的

4、全局声明不同表现

使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声 明的变量则会)。

在全局作用域中,var与const/let声明不同处:用var定义的变量,是全局变量,并成为全局对象的一个属性,用var 定义的变量会覆盖原本存在的全局变量或对象。而用const/let定义的变量它会隔离全局的属性/对象,不会覆盖。

5、const声明

const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且 尝试修改 const 声明的变量会导致运行时错误。

const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象, 那么修改这个对象内部的属性并不违反 const 的限制。

总结

声明变量时优先使用const,如果变量值会被改用let,其次考虑var