ECMAScript 2015 (ES6) 中的“let”和“const”有什么区别?

IT技术 javascript ecmascript-5 ecmascript-6
2021-02-05 08:33:29

我不知道是什么样的区别let,并constES6它们都是块作用域,如以下代码中的示例:

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”?我们可以用“让”代替吗?

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

6个回答

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

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

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

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

在实践中,浏览器并不仅仅从 0% 支持 ECMAScript 2015 (ECMAScript 6) 到 100% 一次性 - 功能会一点一点地添加,直到浏览器完全兼容。JS Bin 所说的“JavaScript”只是意味着您的浏览器当前支持的 ECMAScript 功能——它并不意味着“ES5”或“ES6”或其他任何东西。许多浏览器都支持constlet他们完全支持ES6前,但有些(如Firefox)对待constlet一段时间。这可能是问题的提问者的浏览器支持let,并const却没有正确地实现它们。

其次,像 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()在其上使用但是,这只会使对象本身只读;对象属性的值仍然可以改变。

@Jonny 我确定是。ES6/JavaScript 确实有很多 Swift 没有的编程语言设计方面的约束,在我看来,Swift 的“var”与“let”的区别本身并不像 Rust 的“let mutable”符号那么直观。
2021-03-20 08:33:29
所以我在这里仍然感到困惑:1)如果const没有使某些东西不可变,那么为什么它被称为 const?2) 如果可以使用 重新分配值let,那么它与 有什么不同var我希望在这里得到一些澄清。对不起,我读得越多,我就越困惑,无法确定这些之间的明显区别。
2021-03-23 08:33:29
来自快速背景的非常烦人。Let 应该声明不变的属性。
2021-03-25 08:33:29
@rohan-patel 1)const正在变量名和对象常量之间进行绑定(或“链接”)。如果使用const,该变量名称将始终引用同一个对象。2)let是块范围的,var而是函数范围的。换句话说,如果let在 if 语句中使用,则变量将仅存在于 if 语句中,而如果使用var,则变量将存在于 if 语句所在的函数体内。
2021-03-29 08:33:29
@rohan-patel 至于为什么这两件事很有用:如果您知道变量名称只会分配给对象一次并且不会更改,那么它会使您的代码更容易阅读和思考。至于let, 的let工作方式与大多数其他编程语言中的变量工作方式相同,而var, 则不然。
2021-04-11 08:33:29

您所看到的只是一个实施错误。根据ES6 规范 wiki onconstconst是:

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

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

这是关于 Traceur 未实施Github 问题const

  • 在编程中使用块作用域。
  • 对于每个块,让我们创建自己的新范围,您无法在该块之外访问该范围。
  • 您可以根据需要多次更改值。
  • 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 声明必须被初始化

     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
}

概括:

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

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

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

const 重新分配错误

我们为什么要使用这个?

如果我们知道我们想给一个变量赋值一次并且我们不想重新分配这个变量,那么使用const关键字有以下优点:

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

警告:

尽管用 with 声明的变量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()它来实现这一点。

letconst

ES6let允许您声明一个变量,该变量的范围仅限于块(局部变量)。主要区别在于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关键字附加的变量声明到任何的阻止它被包含在范围内。

申报令

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

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

使用 const

另一方面,使用 ES6const很像使用let,但是一旦赋值,就无法更改。使用const作为一个不变的值,以防止变量意外重新分配:

const num = 42;

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

}

num; // 42

使用const给变量赋值是在现实生活中(如冷冻温度)不变。JavaScriptconst不是要创建不可更改的值,它与值无关,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