Gandalf The Blue

let还是const

December 22, 2019 • ☕️ 1 min read

原文链接On let vs const

我的上一篇文章包括下面这段话:

let vs const vs var: 通常你会选择 let。如果要禁止给变量重新赋值, 则可以使用 const. (有些代码库和程序员比较教条主义,当变量只赋值一次时,会强迫使用 const。)

事实证明这是非常有争议的,引发了Twitter和Reddit上的激烈讨论。似乎大多数人的观点(或至少是最明确表达的观点)是,应尽可能使用 const,只有在需要时才使用 let,并且可以使用 prefer-const ESLint规则来强制执行。

在本文中,我将简要总结我遇到的一些支持论点和反驳论点,以及我对该话题的个人结论。

为什么 prefer-const

  • 一种论点是: 每次都要在letconst之间进行选择是一种心智负担。“始终在可行的地方使用 const”之类的规则使你不必再考虑它,并且可以由linter强制执行。
  • 重新赋值可能引起bug: 在较长的函数中,重新分配变量很容易导致遗漏,这可能会导致bug。 特别是在闭包中,const使你更有信心,你将始终“看到”相同的值。
  • 关于可变的学习: 刚接触JavaScript的人经常会感到困惑,认为const意味着不可变性。 但是,有人可能会指出,学习变量变动(mutation)和赋值之间的区别很重要,并且使用const会迫使你尽早应对这种区别。
  • 无用的赋值: 有时候赋值是根本没有意义的。 例如,使用React Hooks时,从诸如useState之类的Hook中获取的值更像参数。 它们沿一个方向流动。 在赋值中发现错误有助于你更早地了解React数据流。
  • 性能优化: 偶尔有人声称,由于事先知道不会重新分配变量,因此JavaScript引擎可以使使用const的代码运行得更快。

为什么不 prefer-const

  • 意图的丢失: 如果我们在所有可以使用的地方强制使用const,那么对于判断某些变量应不应该被重新赋值是否重要,我们将失去表达这种信息的能力。
  • 不可变性的困扰: 在每次关于为什么你应该首选const的讨论中,总会有人对不变性感到困惑。 这并不奇怪,因为赋值和变量变动都使用相同的=运算符。 作为回应,人们通常被告知他们应该“只是学习该门语言”。 但是,相反的论点是,如果可以防止大多数初学者犯错误的功能同时使初学者感到困惑,那么它其实并不是很有用。 不幸的是,它无助于防止跨越模块并影响每个人的变量变动错误。
  • 避免重新申明的压力: const优先的代码库给在某种条件下会重新分配变量的情况制造了不能使用let的压力。 例如,你可能编写const a = cond ? b : c而不是if条件分支,即使b分支和c分支很复杂并且给它们指定明确的名称很奇怪。
  • 重新赋值可能不会引起bug: 在三种常见的情况下重新赋值会导致错误:当scope很大(例如模块scope或庞大的函数)时,当值是参数时(因此它等于传递的值之外的值是不可预料的), 以及在嵌套函数中使用变量时。 但是,在许多代码库中,大多数变量都不满足以上任何一种情况,并且根本无法将参数标记为常量。
  • 无法性能优化: 据我了解,即使你使用varlet,javascript引擎也已经知道哪些变量仅被赋值一次。 如果我们坚持推断,那么我们也可以推断额外的检查会“创造”性能成本,而不是降低性能成本。 实际上,javascript引擎非常聪明。

我的结论

我根本不在乎。

我将使用代码库中已经存在的任何约定。

如果你在乎的话,请使用可自动检查和修复此问题的linter,以免将let更改为const造成代码评审的延误。

最后请记住,linters的存在是为服务的。 如果一个linter规则使你和你的团队感到不快,请将其删除。 这可能不值得。 请从自己的错误中学习。

Gandalf The Blue

Dan Abramov

Personal blog by shan yang.
Passionate about frontend.