我最近一直在为io.js写很多ES6代码。
我的问题是关于何时使用constlet

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

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

问题是,当我应用此规则时,实际上95%的声明是const。这对我来说很奇怪。我仅将let用于i循环中的for之类的东西,或偶尔用于诸如累积斐波纳契总数之类的东西(在现实生活中很少用)。我对此感到惊讶–事实证明,到目前为止,我的ES5代码中95%的“变量”是针对不变的值。但是在我的代码中看到const感觉有点不对。

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

还是应该保留const用于那些在模块顶部硬编码文字的情况?像const MARGIN_WIDTH = 410;吗?

评论

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

函数foo(){...}优于 foo = function(){...}

@OrangeDog我想听听您的解释,因为我得出的结论恰恰相反。需要注意的是,由于吊装,函数foo(){...}可能在调试时引起轻微的混淆。同样,它的存在意味着我们有两个做相同事情的构造,但是其中一个仅在非常特定的上下文中起作用。 (可以在存在表达式的任何地方使用函数表达式,但只能在语句级别使用函数声明。)如果您过于简洁,则问题可能出在函数表达式语法使用整个单词function。 />
堆栈跟踪使用函数名称代替anon。提升是好的,让我们以自然的顺序定义函数,而不必担心foo未被定义。

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

#1 楼

我在这里的回复不是特定于javascript的。

作为一种经验法则,可以让我以半简单的方式做到这一点的任何语言,我会说总是使用const / final / readonly /无论使用什么尽可能以您的语言被调用。原因很简单,当代码死了很明显时,就可以轻松地进行代码推理。除此之外,在许多语言中,您都可以获得工具支持,告诉您在意外分配给声明为const的变量时您做错了。

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

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

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

这一切都始于const非常自由! ;)与let相比,只写了两个字符,所以继续进行所有操作吧!

评论


const比让字符多两个...

–橙色狗
2015年4月9日在14:49

但是少于不变的少于5个字符。

–陶瓷
2015年4月9日18:57

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

–凯特
15年4月14日在19:52

我同意这个答案,但请记住,在使用诸如纯对象或数组之类的东西时,它们并不是那么明显,因为即使使用“ const”定义它们的属性也可能会发生变化。我曾想到'const'像object.freeze一样工作,但事实并非如此。

–后台
15年5月22日在9:23

@Cerad您的意思是“少四个字符”还是我在这里错过了一些玩笑?

–玛蒂亚斯·拜恩斯(Mathias Bynens)
16年2月5日,9:02

#2 楼

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

从这里:https://developer.mozilla.org/zh-CN/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用于对象/数组。

评论


正确,但是可以预期的IMO-常量是分配给您的const的对象引用。颜色=数字无法正常工作。如果要保护对象属性,可以使用Object.freeze()developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

–约瑟夫·恩格弗罗斯特
15年10月13日在9:43

误导。它是不变的。但是实际的对象属性不是。

–加斯顿·桑切斯(Gaston Sanchez)
15年12月24日在1:33

+1是,引用受到保护,但是就问题而言,在const moment = require('moment')之类的情况下使用它非常愚蠢,除非您是那种担心某人会尝试执行此操作的人稍后再做一下= dead.fish(()=>披萨)。

– MaxWell
16-2-17在22:57



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

– Monokrome
16-10-12在20:24

“对所有非数组/非对象使用const并对对象/数组使用let”这只会使您面临更多的问题...

– Emile Bergeron
19年1月9日在21:57

#3 楼

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

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

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


const将仅防止重新分配,而freeze方法将保护所有立即属性。如果您还需要所有嵌套属性也都是不可变的,则需要递归地对它们进行嵌套。

评论


请注意,Object.freeze是浅的。

–玛蒂亚斯·拜恩斯(Mathias Bynens)
16年5月5日在9:03

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

–科尔·罗伯茨(Cole Roberts)
2016年9月6日在16:36

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

– clean_coding
2016年9月6日19:59

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

–玛蒂亚斯·拜恩斯(Mathias Bynens)
2016年9月6日20:56在

#4 楼

在我的ES6 const不是关于不变性的文章中,我将根据规范完全解释const的含义。

基于这些客观事实,这是我个人的偏爱:


[…]在您的ES6代码中按如下方式使用letconst很有意义:


默认情况下使用const
如果重新绑定(例如,任何形式的绑定),请仅使用let重新分配)是必需的
(在ES6中不应使用var





可能是主观的,这实际上与规范的要求最接近

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

仅将const用于常量就像使用HTML一样<aside>元素仅用于侧边栏内容。

评论


如果它不是常量,为什么还要命名为const?

–nu珠穆朗玛峰
16-09-23在18:48

@nueverest因为这不是const的作用。你读过上面的吗?

–玛蒂亚斯·拜恩斯(Mathias Bynens)
16-09-25在14:55

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

–MrN00b
17年2月28日在3:04

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

– jtr13
18年4月1日在21:43

#5 楼

我的个人方法被认为有助于提高代码的可读性和理解力:


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”,这可能会引起读者的思考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
}



此处有更多评论和将来可能的更新。

评论


第二个代码段看起来像一把枪。

–朱利安
17年2月7日在22:13

#6 楼

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

const public void DoSomething()


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

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