关于ecmascript 6:对所有永远不会改变的变量使用const是否有意义?

Does it make sense to use const for all variables that will never be changed?

给出这样的结果:

1
2
3
4
5
6
const audio = React.findDOMNode(this.refs.audio);
const seeker = React.findDOMNode(this.refs.seeker);
const {left, right} = seeker.getBoundingClientRect();
const seekToPerc = (event.clientX - left) / (right - left);

audio.currentTime = this.props.totalRunTime * seekToPerc;

这是过度使用const吗?我应该在这里使用let吗?


const的使用取决于个人。如果您假装JavaScript是强类型的,那么大多数JavaScript引擎的优化效果最好。因此,const似乎是一个好主意。

一些事实。

  • MDN指出const是块范围的,就像let一样。这只是事实严格模式。
  • 常量必须在声明中赋值。严格地说才是真的模式。
  • 无法重新分配常量。严格和正常都是这样但是在普通的javascript中,分配给常量的操作会自动失败。表示难以查找的Bug的来源。(注意没有好的不使用严格模式的参数)

以差异为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function log(d){console.log(d);}
(function (){
    if(true){
        const a = 10;  // correctly formed use of constant
        const b;       // does not fail
        log(a);        // 10;
        log(b);        // undefined
        b = 10;        // nothing happens. If you have forgoten this is a constant
                       // you will have a hard time knowing this assignment is failing
        log(b);        // undefined
    }
    // scope not respected
    log(a); // 10 const should have block scope. This does not seem to be true
            // in normal javascript
})();

// function in strict mode
// not this is an example only and can not run. It is a compilation of several functions
(function (){
   "use strict";
    if(true){
        const a = 10;    
        const b;     // SyntaxError: Unexpected token. Javascript parsing
                     // stops here and the function will never be called
        a = 20;      // TypeError: Assignment to constant variable
    }
    // scope is respected
    log(a); // ReferenceError: a is not defined
})();

正如您所看到的,在严格模式下使用const和不使用const有很大的区别。除了严格的模式外,在任何情况下使用常量都是很鲁莽的。

性能。Chrome很早就采用了const,至少3年前我还记得使用const。因为我专攻图形,所以性能至关重要。我推断EDCOX1的0个方面将提供一个非常需要的性能优势,与在C/C++中通过简单的代码插入常量值定义的方法大致相同。可悲的是,那天结束时,我完全反对使用const,因为它的性能太差了。

从那时起,情况有所改善。

jspef"常量与变量"

在所有测试中,使用const的速度总是较慢的,但它是边缘的,而且太接近于调用。唯一的例外是块范围声明,它大约是varlet速度的1/3。一个令人惊讶的发现是,let现在在chrome beta上速度非常快,一个月前我不会接近它,这是我给出答案的原因。

OP问…对所有永远不会更改的变量使用const是否有意义?

一年前我会说"永远不要用它"。几个月前我会说,"有一个很好的理由,但VaR更好"。

现在我的答案是,无论什么时候,只要你想让变量永远不变,就一定要使用常量。常量out执行文本,和var一样好。

1
2
3
4
5
const c = 10;
var v = 10;
var a = 10; // this is slower
var a = c; // this is 20% faster
var a = v; // this is about < 1% faster than const.

根据浏览器的变化率,以及最近几个月Chrome上letconst的性能变化。我怀疑常量在年底前会超出vars的性能。(请注意,我使用的是Chrome Beta 47)

我所执行的测试没有为代码优化提供太多的空间,所以我想在使用const时会有额外的性能,这在测试中并不明显。

常量本质上是强类型的,这为JavaScript优化算法提供了一些额外的性能。

使用常量可以提高代码质量。javascript(甚至是严格模式)可以长时间隐藏bug,使用常量可以降低错误分配、意外类型转换等风险。

但是我对警察的使用提出了严重警告。只有在严格模式下使用const,它在普通的javascript中的行为是危险的,并且只会给您带来问题。


blindman67从性能角度给出了一个很好的论证。由于javascript/ecmascript编译器一直在变化/改进,我会考虑从提供更可读/可维护代码的角度来回答这个问题。

标记变量"const"有时很有用,表示值是不可变的。这也代表了编译器不执行const检查的情况,比如标记对象数组const仍然允许您更改该数组中对象的状态。当然,这归根结底就是团队中的编码风格,但我发现大多数人都认为变量定义的常量(即使可以更改)是不可变的。

这个论点的另一方面是过度使用const。当然,您可以在任何地方使用const,它只会使代码更难浏览,更难对其进行更改。我发现在实践中,此类代码的大多数维护工作都是从删除大多数"const"关键字开始的,这样就可以进行必要的额外更改。因此,虽然一开始拥有大量常量看起来像是伟大的代码,但从长远来看,我认为它几乎没有增加可维护性,相反,它使维护更加困难。

tl;dr在您认为增加代码可读性的地方使用const。


我认为const关键字经常被滥用。如果您严格希望编写纯函数(函数编程方法),那么在任何地方使用const都是有意义的。但如果你不想100%地信奉FP宗教,那么我认为你应该使用let。就我个人而言,我使用const来表示实际常量,比如node.js中的const MAX_HEIGHT = 1234;,我认为在文件开头执行const fs = require('fs');也是有意义的。

这是理论上旨在保护开发人员不受影响的功能之一,但我不特别喜欢过度使用const的重构代码;我一直不得不将const变量重命名为let—如果您不小心忘记将声明更改为let,这可能是一个问题,因为它可以n在代码路径执行时导致错误。

在我看来,如果您使用const,那么您需要确保变量在语义上是一个常量,并且在可预见的将来保持不变。此外,我认为警察有时会给人一种错误的安全感,如果它被过度使用。例如,您可以执行const obj = {};,然后稍后修改对象obj.newProperty = 1234;-这是允许的,因为您不会更改对象引用本身,但它似乎在一定程度上破坏了const的目的。