在ES6中应该使用多少个“ let”和“ const”?


214

我最近一直在为io.js写很多ES6代码。没有太多可学习的代码,所以我觉得自己正在定义自己的约定。

我的问题是有关何时使用constVS let

我一直在应用此规则:如果可能,请使用const。仅let当您知道其价值需要改变时才使用。(如果以后发现您需要更改其值,则可以随时将其更改const为a let。)

此规则的主要原因是易于一致地应用。没有灰色区域。

问题是,当我应用此规则时,实际上95%的声明是const。这对我来说很奇怪。我只使用let的东西像i一个for循环,或偶尔搞什么积累斐波那契数总数(不拿出在现实生活中很多)。我对此感到惊讶–事实证明,到目前为止,我的ES5代码中95%的“变量”是针对不变的值。但是,看到const我的代码全都感觉不对。

所以我的问题是:可以使用const这么多吗?我真的应该做类似的事情const foo = function () {...};吗?

还是我应该保留const那些在模块顶部对文字进行硬编码的情况const MARGIN_WIDTH = 410;


7
我怀疑这个问题主要是基于观点的,因此很可能会结束,但是我要花2美分:可以const多使用这个问题。
jhominal 2015年

15
function foo() {...}胜于<anything> foo = function() {...}
OrangeDog

12
@OrangeDog我想听听您的解释,因为我得出的结论恰恰相反。有一个警告function foo() {...},由于吊装,在调试时可能会引起一些混乱。同样,它的存在意味着我们有两个构造函数执行相同的操作,但是其中一个仅在非常特定的上下文中起作用。(您可以在可以存在表达式的任何地方使用函数表达式,但只能在语句级别使用函数声明。)如果您过于简洁,则问题可能出在函数表达式语法使用整个单词function
Keen 2015年

11
堆栈跟踪使用函数名称代替anon。提升是好的,让我们以自然的顺序定义函数,而不必担心foo被不确定。
OrangeDog 2015年

1
这些是要记住的好点,但我尚未确信。现代调试器可以根据分配给它的符号为函数选择正确的显示名称(如果有,如果没有,则可以使用命名函数表达式),从而很好地完成了工作。函数声明的自然顺序是非常主观的。认为自然顺序是先定义基本片段,然后再定义使用它们的片段,这可能是合理的。
基恩(Keen)2015年

Answers:


183

我的回复不是特定于javascript的。

根据任何使用我的语言的经验,我会说只要有可能,总是使用const / final / readonly /无论它在您的语言中被调用什么。原因很简单,当代码死了很明显,什么可以更改和什么不能更改时,就更容易进行代码推理了。除此之外,在许多语言中,您都可以获得工具支持,该工具支持告诉您在意外分配给声明为const的变量时做错了什么。

返回并将const更改为let非常简单。默认情况下使用const会使您在进行此操作之前三思而后行。在许多情况下,这是一件好事。

您看到多少个错误,这些错误涉及到变量的意外更改?我猜很多。我知道我看到的大多数错误都涉及意外的状态更改。通过使用const并不会消除所有这些错误,但是您会摆脱掉许多错误!

同样,许多功能语言都有不可变的变量,其中所有变量默认情况下都是const。例如,以Erlang或F#为例。在没有语言的情况下进行编码无需编码,这是人们喜欢函数式编程的众多原因之一。从这些语言中可以学到很多有关如何管理状态以成为更好的程序员的知识。

而这一切都始于const的极端自由!;)与let相比,只写了两个字符,所以继续const吧!


45
constlet... 多两个字符
OrangeDog 2015年

72
但是少于不变的少于5个字符。
塞拉德2015年

7
这似乎很像val在Scala中使用(将变量声明为不可变的),并且仅var在无法使用时才使用(可变的等效项)val。换句话说,默认情况下,我们将变量声明为不可变的,并且仅在绝对需要时才引入可变性(这可能只是因为可变方法更清洁)。
凯特2015年

7
我同意这个答案,但请记住,在处理诸如普通对象或数组之类的东西时,它们并不是那么明显,因为即使使用“ const”定义它们的属性也可以改变。我曾想过'const'像object.freeze一样工作,但事实并非如此。
2015年

2
@Cerad您的意思是“少四个字符”还是我在这里想笑?
Mathias Bynens'2

57

注意,因为const对象键是可变的。

从这里:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

对象密钥不受保护

考虑这个例子:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

数组也一样:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

我还没有完全决定自己,但是我正在考虑将其const用于所有非数组/非对象以及let用于对象/数组。


34
正确,但可以预期的IMO-分配给的对象引用是恒定的constcolors = numbers不能按预期工作。如果你想保护你的对象属性,你可以使用Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
约瑟夫Engelfrost

16
误导。它是不变的。但是实际的对象属性不是。
加斯顿·桑切斯

1
+1是,参考文献受到保护,但是就问题而言,在类似的情况下使用它是很愚蠢的const moment = require('moment'),除非您是那种担心某人稍后会尝试使用的人moment = dead.fish(() => pizza)
MaxWell

5
也许更现实的担心moment = Date.now()。但是无论如何,如果代码假定一个不变式,则我认为在可能的情况下强制执行它没有错。
James M.

3
不过,没有人说它们不是一成不变的。常见的误解是const的目标是使其不可变,而实际上是要保证名称永远不会引用与初始化对象不同的对象。
monokrome

25

不用担心 const是对JavaScript的惊人补充,我建议您在所有有意义的地方使用它。它使代码更健壮。

当涉及对象时,const将保护您的变量免于重新分配,但是如果您需要不可变的对象,则将需要该Object.freeze方法,请参见下文。

const immutableOject = Object.freeze({immutableProperty: 'foo'});

const将仅防止重新分配,并且该freeze方法将保护所有直接属性。如果您还需要所有嵌套属性也都是不可变的,那么您将需要递归地使用freeze它们。


14
注意那Object.freeze是浅的。
Mathias Bynens '16

@MathiasBynens我遇到了这个评论,我很好奇您的意思是什么。您能详细说明一下吗?
科尔·罗伯茨

@ColeRoberts浅层不变性的概念是对象引用本身是不变的,但是属性仍可以更改时。const关键字仅导致浅层不变性,因此,如果所有属性也应不变,则需要使用Object.freeze。
clean_coding

3
@ColeRoberts这意味着冻结对象(即嵌套对象)内的对象值仍可以进行突变。有关更多信息,请参见mathiasbynens.be/notes/es6-const#immutable-values
Mathias Bynens

19

在我的ES6 const中,关于不变性的文章并不const明确,我将根据规范解释确切的含义。

基于这些客观事实,这是我的个人喜好:

[…]可以使用,let并且const在ES6代码中如下使用:

  • const默认使用
  • let在需要重新绑定(即任何形式的重新分配)时使用
  • var不应在ES6中使用)

尽管可能是主观的,但这实际上与规范的意图最相符。

let默认情况下使用的人通常将const变量视为常量(根据设计,它们不一定是常量!)。对于每个人自己,但我更喜欢将事物用于其预期目的,而不是出于某些虚假的意思,人们根据误解将其分配给他们。

使用const仅常数是喜欢使用的HTML <aside>元素只为侧栏内容。


2
const如果名称不是恒定的,为什么还要命名呢?
nu珠穆朗玛峰,2013年

3
@nueverest因为那不是const目的。你读过上面的吗?
Mathias Bynens

2
@MathiasBynens我认为(唯一?)问题const是它被称为const。这是一个愚蠢的名称(使用javascript),一开始让很多(所有)开发人员感到困惑。如果const已被调用let(尤其是因为let它更短,但const更普遍),又再调用其他名称,则IMO更好let
MrN00b

@MathiasBynens我明白了,但是为什么要这样称呼呢?正如此页面所展示的,这造成了巨大的混乱。
jtr13 '18

4

我个人的想法是帮助提高代码的可读性和理解力:


let仅适用于短期变量,它们在一行中定义,之后不会更改。通常,那些仅用于减少键入量的变量。例如:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

const所有已知在整个模块中保持不变的名称。不包括局部常量值。在value上面的例子,例如,在其范围不变,并可能与声明const,但因为有许多次迭代,为每一个有具有相同的值的名称,“价值”,到以为可以欺骗读者value总是相同。模块和函数是const变量的最佳示例:

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

var对于可能是可变的一切。即使使用本地常量,并且不适合let(即,它们不能在简单的直接声明中完成),也可能使人们混淆阅读代码的名称适用于使用进行声明var。例如:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

进一步的评论和未来可能的更新这里


10
第二个代码段看起来像一把枪。
朱利安

1

JavaScript有点特殊,因为变量可以是函数,但可以考虑使用C#,Java或其他类似的C样式语言:

const public void DoSomething()

const很奇怪,这是因为这些语言中的方法声明一旦被编译为其他内容就无法更改,而无论如何(忽略可能存在的一些可怕的骇客),它们都是这样做的。

为什么JavaScript会有所不同?因此它不是经过编译的,但这并不意味着我们应该放弃编译器可以提供的安全性。使用const关键字可以提高安全性,这肯定会导致更强大的应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.