【问题标题】:What is the difference between 'let' and 'const' ECMAScript 2015 (ES6)?'let' 和 'const' ECMAScript 2015 (ES6) 有什么区别?
【发布时间】:2014-04-14 00:32:50
【问题描述】:

我想知道 ES6 中的letconst 有什么区别。它们都是块作用域,如以下代码中的示例:

const PI = 3.14;
console.log(PI);

PI = 3;
console.log(PI);

const PI = 4;
console.log(PI);

var PI = 5;
console.log(PI);

在 ES5 中,输出将是:

3.14
3.14
3.14
3.14

但在 ES6 中它将是:

3.14
3
4
5

我想知道为什么 ES6 允许const 值的变化,问题是为什么我们现在应该使用'const'?我们可以用'let'代替吗?

注意jsbin可用于测试,选择JavaScript运行ES5代码和Traceur使用 ES6 功能运行它。

【问题讨论】:

  • 规范仍在开发中,更不用说实现了。如果您重新定义 const,我的 chrome;32.0.* 将保持沉默,但它保持不变。你是如何测试你的代码的?
  • 我不确定 ESMAScript6 术语,但在其他语言中,这不会算作“const 值的更改[ing]”,它会 shadow 与不同的绑定。
  • @iccthedral: I JSBin -> 选择 Javascript 来运行 ECMAScript5 代码和 Traceur 来使用 ECMAScript6 功能运行它。
  • 可能显示 Traceur 生成的代码 - 可能它有问题。请注意,如果严格实现,您的示例根本不会在 ES5 中运行,因此您只是体验到当前浏览器对 const 的支持——例如,某些浏览器只是将 at 视为 var

标签: javascript ecmascript-5 ecmascript-6


【解决方案1】:

letconst 之间的区别在于,一旦使用const 将值/对象绑定到变​​量,就不能重新分配给该变量。换句话说例子:

const something = {};
something = 10; // Error.

let somethingElse = {};
somethingElse = 1000; // This is fine.

问题详情声称这是对 ES5 的更改——这实际上是一种误解。在只支持 ECMAScript 5 的浏览器中使用 const 总是会抛出错误。 const 语句在 ECMAScript 5 中不存在。其中的行为要么是 JS Bin 误导了正在运行的 JavaScript 类型,要么是浏览器错误。

在实践中,浏览器并不是一次性从 0% 支持 ECMAScript 2015 (ECMAScript 6) 到 100% — 功能是逐位添加的,直到浏览器完全兼容。 JS Bin 所说的“JavaScript”只是指您的浏览器当前支持的任何 ECMAScript 功能——它并不意味着“ES5”或“ES6”或其他任何东西。许多浏览器在完全支持 ES6 之前就支持 constlet,但有些浏览器(如 Firefox)在一段时间内将 const 视为 let。提问者的浏览器可能支持letconst,但没有正确实现。

其次,像 Babel 和 Traceur 这样的工具不会让 ES6 在旧版浏览器中“运行”——而是将 ES6 代码转换为 ES5 做大致相同的事情。 Traceur 可能会将const 语句转换为var 语句,但我怀疑它总是强制执行const 语句的语义在ES5 中完全复制。使用 JS Bin 使用 Traceur 运行 ES6 不会得到与在完全符合 ES6 规范的浏览器中运行 ES6 完全相同的结果。


请务必注意,const 不会使值或对象不可变。

const myArray = [];
myArray.push(1); // Works fine.
myArray[1] = 2; // Also works fine.
console.log(myArray); // [1, 2]
myArray = [1, 2, 3] // This will throw.

目前使对象(浅)不可变的最佳方法可能是在其上使用Object.freeze()。但是,这只会使对象本身成为只读的;对象的属性值仍然可以改变。

【讨论】:

  • 所以我在这里仍然感到困惑:1)如果const 没有使某些东西不可变,那么为什么将它称为const? 2) 如果您可以使用let 重新分配值,那么它与var 有何不同?我会很感激这里的一些澄清。对不起,我读了更多关于这方面的内容,我很困惑,无法确定它们之间的明显区别。
  • @rohan-patel 1) const 在变量名和对象常量之间进行绑定(或“链接”)。如果您使用const,该变量名将始终引用同一个对象。 2) let 是块作用域,而var 是函数作用域。换句话说,如果您在 if 语句中使用 let,则该变量将仅存在于 if 语句中,而如果您使用 var,则该变量将存在于 if 语句所在的函数体内在。
  • @rohan-patel 至于为什么这两件事很有用:如果你知道一个变量名只被分配给一个对象一次并且没有改变,它会让你的代码更容易阅读和想一想。至于letlet 的工作方式与大多数其他编程语言中变量的工作方式相同,而 var 则不然。
  • 来自 swift 背景非常烦人。 Let 应该声明不变的属性。
  • @Jonny 我敢肯定。 ES6/JavaScript 确实有很多 Swift 所没有的编程语言设计方面的约束,而且在我看来 Swift 的 'var' 与 'let' 区别本身并不像 Rust 的 'let mutable' 表示法那么直观。
【解决方案2】:

您看到的只是一个实施错误。根据ES6 spec wiki on constconst是:

一个初始化一次,之后只读的绑定形式是有用的,并且有 现有实现中的先例,以 const 的形式 声明。

它是只读的,就像现在一样。 Traceur 和 Continuum 中 const 的 ES6 实现有问题(他们可能只是忽略了它)

这是Github issue regarding Traceur not implementing const

【讨论】:

    【解决方案3】:

    • 在编程中使用块作用域。
    • 为每个块创建自己的新范围,您无法在该块之外访问。
    • 可以根据需要多次更改值。
    • let 对于绝大多数代码来说都非常有用。它可以大大提高您的代码可读性并减少编程错误的机会。

      let abc = 0;
      
      if(true)
       abc = 5 //fine
      
      if(true){
        let def = 5
      }
      console.log(def)
      

    常量

    • 它允许您使用变量保持不变。
    • const 对于可读性和可维护性来说都是一种很好的做法,并且避免使用魔法文字,例如

      // Low readability
      if (x > 10) {
      }
      
      //Better!
      const maxRows = 10;
      if (x > maxRows) {
       }
      
    • 必须初始化常量声明

       const foo; // ERROR: const declarations must be initialized
      
    • const 是块作用域,就像我们在 let:+ 中看到的那样
    const foo = 123;
    if (true) {
        const foo = 456; // Allowed as its a new variable limited to this `if` block
    }
    

    【讨论】:

      【解决方案4】:

      总结:

      letconst 关键字都是声明块作用域变量的方法。不过有一个很大的区别:

      • 可以重新分配使用let 声明的变量。
      • 使用const 声明的变量必须在声明时进行初始化,并且不能重新赋值。

      如果您尝试重新分配使用 const 关键字声明的变量,您将收到以下错误(chrome devtools):

      我们为什么要使用这个?

      如果我们知道要分配一次变量并且不想重新分配变量,则使用 const 关键字具有以下优势:

      • 我们在代码中表示不想重新分配变量。这样,如果其他程序员查看您的代码(甚至是您自己的代码,您之前编写的代码),您就知道不应重新分配使用 const 声明的变量。通过这种方式,我们的代码变得更具声明性并且更易于使用。
      • 我们强制执行不能重新分配变量的原则(JS引擎抛出错误)。这样,如果您不小心尝试重新分配一个不打算重新分配的变量,您可以在较早的阶段检测到这一点(因为它已记录到控制台)。

      警告:

      虽然用const 声明的变量不能重新分配,但这并不意味着分配的对象不可变。例如:

      const obj = {prop1: 1}
      
      // we can still mutate the object assigned to the 
      // variable declared with the const keyword
      obj.prop1 = 10;
      obj.prop2 = 2;
      
      console.log(obj);

      如果您还希望您的对象不可变,您可以使用Object.freeze() 来实现此目的。

      【讨论】:

        【解决方案5】:

        letconst

        ES6 let 允许您声明一个在块范围内限制的变量(局部变量)。主要区别在于var 变量的作用域是整个封闭函数:

        if (true) {
          var foo = 42; // scope globally
        }
        
        console.log(foo); // 42
        

        let 范围

        if (true) {
          let foo = 42; // scoped in block
        }
        
        console.log(foo); // ReferenceError: bar is not defined
        

        在函数范围内使用var与使用let是一样的:

        function bar() {
          var foo = 42; // scoped in function
        }
        
        console.log(foo); // ReferenceError: bar is not defined
        

        let 关键字将变量声明附加到它所包含的任何块的范围内。

        申报顺序

        letvar 之间的另一个区别是声明/初始化顺序。在声明之前访问由let 声明的变量会导致ReferenceError

        console.log(a); // undefined
        console.log(b); // ReferenceError: b is not defined
          
        var a = 1;
        let b = 2;
        

        使用const

        另一方面,使用 ES6 const 很像使用 let,但是一旦赋值,就不能更改。使用const作为不可变值,防止变量意外重新赋值:

        const num = 42;
        
        try {
          num = 99;
        } catch(err) {
          console.log(err);
          // TypeError: invalid assignment to const `number'
        
        }
        
        num; // 42
        

        使用const 分配现实生活中不变的变量(例如冷冻温度)。 JavaScript const 不是要制作不可更改的值,它与值无关,const 是为了防止将另一个值重新分配给变量并使变量为只读。但是,值总是可以改变的:

        const arr = [0, 1, 2];
        arr[3] = 3; // [0, 1, 2, 3]
        

        要防止值更改,请使用Object.freeze()

        let arr = Object.freeze([0, 1, 2]);
        arr[0] = 5;
        
        arr; // [0, 1, 2]
        

        使用letFor 循环

        let 真正闪耀的一个特殊情况是在for 循环的标题中:

        for (let i = 0; i <= 5; i++) {
          console.log(i);
        }
        
        // 0 1 2 3 4 5
        
        console.log(i); // ReferenceError, great! i is not global
        

        【讨论】:

          【解决方案6】:

          let 和 const

          使用letconst 声明的变量消除了提升的特定问题,因为它们的作用域是块,而不是函数。

          如果在代码块内使用letconst 声明变量(用花括号 { } 表示),则该变量会停留在所谓的临时死区,直到处理变量的声明.这种行为会阻止变量在被声明之前被访问。

          let 和 const 的使用规则

          letconst 还有一些其他有趣的属性。

          • let 声明的变量可以重新分配,但不能 在同一范围内重新声明。
          • 必须为使用const 声明的变量分配一个初始值,但是 不能在同一范围内重新声明,也不能重新分配。

          用例

          最大的问题是什么时候应该使用letconst?一般的经验法则如下:

          • 当您计划将新值重新分配给变量时,请使用 let,并且
          • 当您不打算将新值重新分配给 变量。

          由于const 是声明变量的最严格方式,因此建议您始终使用const 声明变量,因为您知道标识符在整个过程中都不会改变,这将使您的代码更容易推理程序的生命周期。如果您发现需要更新或更改变量,则返回并将其从const 切换到let

          【讨论】:

            【解决方案7】:
            • var 声明是全局作用域或函数作用域,而 let 和 const 是块作用域。

            • var 变量可以在其范围内更新和重新声明;让 变量可以更新但不能重新声明;const 变量不能更新也不能重新声明。

            • 它们都被提升到了范围的顶部。但是虽然 var 变量用 undefined 初始化,let 和 const 变量是 未初始化。

            • 虽然 var 和 let 可以在不初始化的情况下声明,但 const 必须在声明期间初始化。

            【讨论】:

              【解决方案8】:

              以下是我记下的一些笔记,对我在这个问题上有所帮助。还将constletvar 进行比较。

              这里是关于var:

              // Var
              // 1. var is hoisted to the top of the function, regardless of block
              // 2. var can be defined as last line and will be hoisted to top of code block
              // 3. for undefined var //output error is 'undefined' and code continues executing
              // 4. trying to execute function with undefined variable
              // Example: // log(myName); // output: ReferenceError: myName is not defined and code stops executing 
              

              这里是关于letconst

              // Let and Const
              // 1. use `const` to declare variables which won't change
              // 2. `const` is used to initialize-once, read-only thereafter
              // 3. use `let` to declare variables which will change
              // 4. `let` or `const` are scoped to the "block", not the function
              // 5. trying to change value of const and then console.logging result will give error
              // const ANSWER = 42;
              // ANSWER = 3.14159;
              // console.log(ANSWER);
              // Error statement will be "TypeError: Assignment to constant variable." and code will stop executing
              // 6. `let` won't allow reference before definition
              // function letTest2 () {
              //   log(b);
              //   let b = 3;}
              // Error statement will be "ReferenceError: b is not defined." and code will stop executing
              

              【讨论】:

                【解决方案9】:

                变量

                The var keyword was introduced with JavaScript. 
                It has global scope.    
                It can be declared globally and can be accessed globally.   
                Variable declared with var keyword can be re-declared and updated in the same scope.
                Example:
                function varGreeter(){
                  var a = 10;        
                  var a = 20; //a is replaced
                  console.log(a);
                }
                varGreeter();
                

                它被吊起来了。

                Example:
                {
                  console.log(c); // undefined. 
                  //Due to hoisting
                  var c = 2;
                }
                

                The let keyword was added in ES6 (ES 2015) version of JavaScript.
                It is limited to block scope.
                It can be declared globally but cannot be accessed globally.
                Variable declared with let keyword can be updated but not re-declared.
                Example:
                function varGreeter(){
                  let a = 10;        
                 let a = 20; //SyntaxError: 
                 //Identifier 'a' has already been declared
                  console.log(a);
                }
                varGreeter();
                

                它没有被吊起。

                Example:
                {
                  console.log(b); // ReferenceError: 
                  //b is not defined
                  let b = 3;
                }
                

                全局对象属性

                  var no1 = "123";  // globally scoped
                  let no2 = "789"; // globally scoped
                
                  console.log(window.no1); // 123
                  console.log(window.no2); // undefined
                

                重新声明:

                '使用严格';

                  var name= "Keshav";
                  var name= "Keshav Gera"; // No problem, 'name' is replaced.
                
                  let surname= "Rahul Kumar";
                  let surname= "Rahul Khan "; // SyntaxError: Identifier 'surname' has already been declared
                

                吊装

                function run() {
                    console.log(name); // undefined
                    var name= "Keshav";
                    console.log(name); // Keshav
                }
                
                 run();
                
                 function checkHoisting() {
                     console.log(name); // ReferenceError
                     let name= "Keshav";
                     console.log(name); // Keshav
                 }
                 checkHoisting();
                

                注意:如果是var,你会得到undefined,如果是let,你会得到引用错误

                常量

                It allows you to be immutable with variables.
                

                必须初始化常量声明

                const name; // ERROR: const declarations must be initialized
                
                A const is block scoped like we saw with let:+
                
                const num = 10;
                if (true) {
                 const num = 20; // Allowed as its a new variable limited to this `if` block
                }
                

                【讨论】:

                  【解决方案10】:
                  /*
                  // declaration of const in same block scope is not allowed
                  const a = 10;
                  const a = 15; //Redeclaration of const a Error
                  console.log(`const outer value `+a);
                  */
                  
                  /*
                  //declaration of const in different block scope is allowed
                  const a = 10;
                  console.log(`outer value of a `+a)
                  {
                      const a = 15; //Redeclaration of const allowed in different block scope
                      console.log(`ineer value of a `+a);
                  }
                  */
                  
                  /*
                  // re assigning const variable in any block scope is not allowed
                  const a = 10;
                  a = 15; //invalid assignment to const 'a'
                  {
                      a = 15;  //invalid assignment to const 'a'
                  }
                  */
                  
                  /*
                  // let also can not be re declared in the same block scope
                  let a = 10;
                  let a = 15; //SyntaxError: redeclaration of let a
                  */
                  
                  /*
                  // let can be redeclared in different block scope
                  let a = 10;
                  {
                      let a = 15; //allowed.
                  }
                  */
                  
                  /*
                  // let can be re assigned in same block or different block
                  let a = 10;
                  a = 15; //allowed for let but for const its not allowed.
                  */
                  
                  /*
                  let a = 10;
                  {
                      a = 15; //allowed
                  }
                  */
                  

                  【讨论】:

                  • 根本没有解决问题。此外,如果没有必要,请不要在代码中使用注释。仅对将导致错误的代码使用注释或将它们用于实际的 cmets。这个问题在几年前就已经得到了很好的回答,所以也没有必要添加这个答案,因为它没有为问题提供任何额外的信息。
                  猜你喜欢
                  • 2014-03-02
                  • 2018-12-22
                  • 2010-10-29
                  • 2022-07-21
                  • 2013-09-22
                  相关资源
                  最近更新 更多