浅析JS中的let、const 与 var 的区别?

157 阅读3分钟

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

let、const、与var的区别?

0301.PNG

  • var定义的变量可被更改,如果不初始化而直接使用也不会报错
  • let定义的变量和var类似,但作用域在当前声明的范围内
  • cons定义的变量只可初始化一次且作用域内不可被更改,使用之前必须初始化
  1. var

    • var 声明作用域

      使用var操作符定义的变量会成为包含它的函数的局部变量

      例如:使用var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁

      function test(){
          var msg = "hello"; //局部变量
      }
      test();
      console.log(msg); //报错(msg is not defined)
      //这里msg是在test函数内部定义的,调用test()函数之后,变量msg会随即被销毁,因此控制台会报错
      

      不过,需要注意的是,如果函数内定义变量时省略var,此时创建的就是一个全局变量;只要调用一次test函数,就会定义msg变量,并且可以在函数外部访问到。(虽然可以通过省略var定义全局变量,但不推荐这样做)

    • var 声明提升

      使用var 声明的变量会自动提升到函数作用域顶部;

      function foo() {
          console.log(num);
          var num = 13;
      }
      foo(); //undefined
      

      运行后发现并没报错,是因为运行时把它看成等价于如下代码:

      function foo() {
          var num;
          console.log(num);
          num = 13;
      }
      foo(); //undefined
      

      这就是所谓的提升(host),也就是把所有变量声明都拉到函数作用域的顶部。还有,反复多次使用var声明同一个变量也没有问题。

  1. let

    • let与var的作用差不多,但有着非常重要的区别。最明显的就是,let声明的范围是块作用域,而var声明的范围是函数作用域。

      if(true) {
          var name = 'Du';
          console.log(name); //Du
      }
      console.log(name); // Du
      
      if(true) {
          let age = 18;
          console.log(age); // 18
      }
      console.log(age); // ReferenceError:age未定义
      

      在这里,age之所以不能在if块之外被引用,是因为它的作用域仅限于该块内部。

    • let声明的变量不会在作用域中被提升

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

    • 使用var的时候,最常见的问题就是对迭代变量的奇特声明和修改:

      for(var i=0; i<5; i++) {
          setTimeout(() => console.log(i),0)
      }
      //你可能以为会输出 0、1、2、3、4
      //实际上输出 5、5、5、5、5
      

      之所以会出现这样的情况,是因为在退出循环时,迭代变量保存的就是导致退出循环的值( 5 )。在之后执行超时逻辑时,所有的i都是同一个变量,因此输出的都是同一个最终值。而使用let声明时:

      for(let i=0; i<5; i++) {
          setTimeout(() => console.log(i),0)
      }
      //输出 0、1、2、3、4
      

      JS引擎在后台会为每个迭代循环声明一个新的迭代变量。每个setTimeout引用的都是不同的变量实例,所以会输出我们期望的值。

      这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for-in和for-of循环

  1. const

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

    • const声明的作用域也是块

      const name = 'joy';
      if(true) {
          const name = 'du';
      }
      console.log(name); //joy
      

声明风格及最佳实践:

  1. 不使用var
  2. const 优先,let 次之(使用const声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现非法的赋值操作。在提前知道未来会有修改时,再使用 let)