【问题标题】:Does it make sense to use const for all variables that will never be changed?对所有永远不会更改的变量使用 const 是否有意义?
【发布时间】:2015-10-23 06:02:56
【问题描述】:

鉴于这样的事情:

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 放在任何设计为恒定的东西上。
  • There are those who think const 在 ES6 中被过度使用。我个人不在那个阵营 - 如果你不打算重新分配这些变量,我会保留它们const

标签: ecmascript-6 constants


【解决方案1】:

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

一些事实。

  • MDN 声明 const 是块范围的,如 let。这只是真的 在严格模式下。
  • 必须在声明时为常量赋值。严格来说才是真的 模式。
  • 无法重新分配常量。这在严格和正常情况下都是如此 但是在普通的javascript中,分配给一个常量会默默地失败 表示难以找到错误的来源。 (注意没有好的 不使用严格模式的论据)

以差异为例

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。由于我专攻图形,因此性能至关重要。我推断const 将提供非常需要的性能优势,这与#define 在C/C++ 中通过简单的代码插入常量值实现的方式非常相似。可悲的是,到那天结束时,我完全反对使用 const,因为它的性能很糟糕。

从那以后它有所改善。

jsperf "Consts V Vars"

使用const 在所有测试中始终较慢,但它是微不足道的并且太接近调用。唯一的例外是块范围声明,它的速度大约是 varlet 的 1/3。一个令人惊讶的发现是 let 现在在 Chrome Beta 上非常快,一个月前我不会靠近它,这个事实就是我回答的原因。

OP 问... 对所有永远不会改变的变量使用 const 有意义吗?

一年前我会说“永远不要使用它”。几个月前我会说,“有充分的理由,但 var 更好”。

现在我的回答是,只要您希望变量永不改变,就绝对使用常量。常量 out 执行文字并且与 var 一样好。

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.

根据浏览器的变化速度,以及过去几个月 letconst在 Chrome 上的性能变化。我怀疑常量将在今年年底前执行 vars。 (请注意我使用的是 Chrome Beta 47)

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

常量本质上是强类型的,这为 javascript 优化算法提供了一些可用于提供额外性能的东西。

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

但是 我对 const 的使用提出了很大的警告。 只能在严格模式下使用 const,它在普通 javascript 中的行为是危险的,只会给你带来问题。

【讨论】:

  • 哇,谢谢!我在 SO 上收到的最好的答案之一。 :)
  • 我喜欢在第一行阅读“使用常量提高代码质量”:-)
  • 我不能那样做@Bergi 在没有"use strict" 的情况下使用const 是有风险的。我希望人们阅读所有答案并理解,而不仅仅是标题。
  • 当然,尽管我希望关心代码质量的人已经在使用严格模式:-)。而且我仍然觉得这个答案可以使用 tl;dr - 虽然您关于性能的轶事很有趣,但它们并没有真正回答主要问题。
  • 没有明确的答案。让或常量。我喜欢常量,我的主要关注点是性能。如果 OP 是为他自己编码,那么这是他的个人喜好。如果他是团队的一员,那么应该有一个样式指南和代码约定文档应该遵循。如果它是供公众使用的,那么目前有太多的 IE 副本无法使用任何 ES6 功能。
【解决方案2】:

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

标记一个变量'const'有时很有用,表示一个值是不可变的。这也代表编译器不强制执行 const 检查的情况 - 就像标记对象数组 const 仍然允许您更改该数组中对象的状态。这当然归结为团队内部的编码风格,但我发现大多数人都认为变量定义的 const,即使可以更改,也应该是不可变的。

这个论点的另一方面是过度使用 const。当然,你可以在任何地方使用 const,它只是让代码更难通过,更难对其进行更改。我发现在实践中,此类代码的大多数维护工作都是从删除大部分“const”关键字开始的,以便可以进行必要的额外更改。因此,虽然拥有大量常量一开始可能看起来很棒的代码,但从长远来看,我认为它几乎不会增加可维护性,相反,它会使维护变得更加困难。

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

【讨论】:

  • 感觉javascript没有常量的命名标准。就目前而言,只有通过查看声明才能知道特定变量是否为常量。我个人的做法是让所有常量都用下划线分隔的大写单词。它可以立即识别常数并有助于维护。但是由于某种原因,它在 javascript 中看起来是错误的,并且前缀或后缀是一种糟糕的命名习惯。可能是另一天的问题。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2015-07-30
    • 2012-03-02
    • 1970-01-01
    • 2011-05-31
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多