JavaScript 中的常量:何时使用它,是否有必要?

IT技术 javascript node.js constants immutability
2021-02-09 16:49:53

我最近const在 JavaScript 中遇到了关键字。据我所知,它用于创建不可变变量,并且我已经测试以确保它不能被重新定义(在 Node.js 中):

const x = 'const';
const x = 'not-const';

// Will give an error: 'constant 'x' has already been defined'

我意识到它尚未在所有浏览器中标准化 - 但我只对Node.js V8的上下文感兴趣,并且我注意到某些开发人员/项目似乎在var关键字可用于一样的效果。

  • 什么时候用const代替合适var
  • 每次声明一个不会被重新分配的变量时都应该使用它吗?
  • 如果var使用它来代替 const或反之亦然,它实际上有什么区别吗?
6个回答

您的问题有两个方面:使用const代替的技术方面是var什么以及这样做与人类相关的方面是什么。

技术差异是显着的。在编译语言中,常量将在编译时被替换,它的使用将允许其他优化,如死代码删除,以进一步提高代码的运行时效率。最近(松散使用的术语)JavaScript 引擎实际上编译 JS 代码以获得更好的性能,因此使用 const 关键字会通知他们上述优化是可能的并且应该完成。这会带来更好的性能。

与人类相关的方面是关于关键字的语义。变量是包含预期会更改的信息的数据结构。常量是包含永远不会改变的信息的数据结构。如果有错误的余地,var应始终使用。然而,并不是所有在程序生命周期中永远不会改变的信息都需要用const. 如果在不同情况下信息应该更改,请使用var来指示,即使实际更改没有出现在您的代码中。

@Rudie 您正在寻找的功能称为冻结对象。const只是防止将“变量”重新分配给另一个值。const a = {}; a = {};在严格模式下会抛出错误。
2021-03-14 16:49:53
If there is room for error, var should always be used. 今天这不再适用,像 ESLint 这样的工具会立即指出const违规行为。
2021-03-15 16:49:53
对于所有关于 const 更改的阅读,您必须记住对象的变量如何工作,您的变量只不过是对象的地址位置,因此虽然对象是可变的,但使用 const 定义时指向该对象的指针却不是。
2021-03-16 16:49:53
干杯,我认为 Mozilla / Google 不会无缘无故地向 JS 引擎添加 const 支持。我会确保在适用的情况下使用 const。
2021-03-17 16:49:53
const对象似乎是可变的,所以我不确定 JS 编译器到底有多严格。也许“使用严格”模式也会有所不同。
2021-04-09 16:49:53

2017年更新

这个答案仍然受到很多关注。值得注意的是,这个答案是在 2014 年初发布的,从那时起发生了很多变化。支持现在是常态。所有现代浏览器现在都支持,const因此使用起来应该非常安全,没有任何问题。


2014 年的原始答案

尽管有相当不错的浏览器支持,但我暂时避免使用它。来自MDN 的文章const

const 的当前实现是 Mozilla 特定的扩展,不是 ECMAScript 5 的一部分。Firefox 和 Chrome (V8) 支持它。从 Safari 5.1.7 和 Opera 12.00 开始,如果您在这些浏览器中使用 const 定义变量,您以后仍然可以更改其值。它在 Internet Explorer 6-10 中不受支持,但包含在 Internet Explorer 11 中。 const 关键字当前在函数范围内声明常量(就像用 var 声明的变量一样)。

然后接着说:

const将由 ECMAScript 6 定义,但具有不同的语义。与使用 let 语句声明的变量类似,使用 const 声明的常量将是块作用域的。

如果您确实使用,const您将不得不添加一种解决方法来支持稍旧的浏览器。

注意 ES6 在 2014 年 8 月收到了功能冻结。2015 年 7 月,该标准正式发布。如果您现在正在阅读本文,则意味着如果您的代码由最新引擎管理,则您应该遵循已接受的答案。
2021-03-13 16:49:53
@NicolaeSurdu 当然。它也是从 2014 年 1 月开始的,所以现在在 2017 年可能大部分是多余的。
2021-03-22 16:49:53
James 感谢您指出支持方面。恕我直言,所有 javascript 答案都应包括浏览器支持细分。很好地解释
2021-03-30 16:49:53
OP 问题是 node.js 特定的
2021-04-03 16:49:53
很好的答案 - 虽然我已经阅读了 MDN 上的文章。正如我所说,我更感兴趣的是V8是否真的会以不同的方式对待 const 和 var。我认为@Tibos 澄清了这一点。
2021-04-08 16:49:53

至于为什么要使用constTibos 的回答很棒。

但是你说:

据我所知,它用于创建不可变变量

那是错误的改变变量与重新分配不同:

var hello = 'world' // Assigning
hello = 'bonjour!' // Reassigning

使用 const,你不能这样做:

const hello = 'world'
hello = 'bonjour!' // Error

但是你可以改变你的变量:

const marks = [92, 83]
marks.push(95)
console.log(marks) // [92, 83, 95] -> the variable has been mutated.

因此,任何在使用=符号的情况下更改变量值的过程都是在改变变量。

注意:+=例如是...重新分配!

var a = 5
a += 2 // Is the same as a = a + 2

所以,底线是:const不会阻止你改变变量;它可以防止您重新分配它们。

来到这里是因为我试图const在数组的上下文中理解(类似于@chharvey 使用的示例)。在的情况下const countArray = countup(n - 1); countArray.push(n);const是,在每次重新分配。那么为什么使用const而不是var呢?
2021-03-13 16:49:53
“但是你说:<<据我所知,它用于创建不可变变量>> 那是错误的改变变量与重新分配不同”不,不是。重新分配正在改变变量。您正在谈论改变变量中的引用所指的对象。那是完全不同的事情。
2021-03-17 16:49:53
@YCode 没有。当您使用时const countArray,它将永远不会被重新分配。您仍然可以推送到数组,这会更改其成员和长度,但我们不称之为重新分配。当您想防止重新分配时使用const代替letvar顺便说一句,如果您确实想允许重新分配,let几乎总是比var.
2021-03-22 16:49:53
@chharvey 谢谢!你的回答让我想到了“值传递 vs 引用传递”,这是一个新概念,也是一个奇怪的概念——值修改≠重新赋值。任何需要进一步解释的人都应该在这里查看答案:stackoverflow.com/q/46131828/5965865
2021-03-31 16:49:53
您的陈述“任何在使用=符号情况下更改变量值的过程都是静音”在技术上是错误的。例如,const marks=[92,83]; marks[2]=95; console.log(marks)将输出[92, 83, 95]. marks已经通过等号进行了变异。
2021-04-05 16:49:53

综合前面的答案,声明常量变量有一个明显的优势,除了性能原因:如果你不小心尝试在代码中更改或重新声明它们,程序将分别不会更改值或抛出错误。

例如,比较:

// Will output 'SECRET'

const x = 'SECRET'
if (x = 'ANOTHER_SECRET') {  // Warning! Assigning a value variable in an 'if' condition
    console.log (x)
}

和:

// Will output 'ANOTHER_SECRET'

var y = 'SECRET'
if (y = 'ANOTHER_SECRET') {
    console.log (y)
}

或者

// Will throw TypeError: const 'x' has already been declared

const x = "SECRET"

/* Complex code */

var x = 0

// Will reassign y and cause trouble

var y = "SECRET"

/* Complex code */

var y = 0
您应该说这种“不可变”行为仅适用于字符串、基本类型。使用对象、数组等可以更改值,但不能重新分配新的“对象”,例如 const a = ["a","b"]; a = []; 会抛出错误,否则有可能
2021-03-28 16:49:53
使用 const 非常像访问修饰符,真正的不变性不是目标。
2021-03-30 16:49:53
您应该有一个示例,您也可以尝试更改常量的值。
2021-04-03 16:49:53

const不是一成不变的。

来自MDN

const 声明创建对值的只读引用。这并不意味着它持有的值是不可变的,只是变量标识符不能重新分配。

JS 原语总是不可变的。使用const与否不影响。
2021-03-24 16:49:53
不过这有点误导。对于数字、字符串、布尔值等(原语)const是不可变的。对于对象和数组,它不能重新分配,但可以更改内容(例如 array.push)。
2021-04-02 16:49:53
一个const变量肯定是不可变的。现在的问题不在于是否const赋予不变性,它是什么const胙不变性?如果变量持有对对象的引用,则该引用是不可变的。变量引用的对象的可变性是完全独立的事情。
2021-04-06 16:49:53
@Dodekeract 因此根据定义它不是一成不变的。如果值可以更改,则它不是不可变的,尽管它对于您列出的原语来说是不可变的
2021-04-08 16:49:53