正确使用const在JavaScript中定义函数


181

我想知道const在JavaScript中可以使用哪种类型的值(特别是函数)设置任何限制。这有效吗?当然可以,但是出于某种原因,它是否被视为不良做法?

const doSomething = () => {
   ...
}

是否应该在ES6中以这种方式定义所有功能?似乎并没有流行起来。

感谢您的任何评论!


您似乎在问多个问题:1)“我对使用JavaScript中的const可以设置哪种类型的值是否有限制感到兴趣” 2)“这是否有效?” 是。3)“出于某种原因,它是否被认为是不好的作法?”我猜它已经存在了很长的时间,无法对此发表任何评论,但是我不明白为什么这应该是一种便笺式练习。与没什么不同var doSomething = <function def>;。4)“是否应该在ES6中以这种方式定义所有功能?” 对我来说似乎很麻烦。我喜欢函数声明。大家自己。
菲利克斯·克林

1
我的看法(观点,不是事实),如果您要禁止重新定义函数,这是有道理的。无论是理智的,还是有一定的功能用途,这都是值得商bat的。如果你觉得它适合你使用的情况下,我不认为有人可以说你的决定,并认为它不好的做法。
Mjh 2015年

4
我想问题是您想要实现什么const。是否要防止自己覆盖该功能?我假设您知道您的代码无论如何都不会这样做。您是否要表达的意图doSomething,即它具有功能且不改变其值?我认为函数声明也清楚地传达了这一意图。因此,如果您需要防止覆盖的“运行时保护”,那就去吧。否则,我看不出太多好处。当然,如果您主要习惯使用var foo = function() {};,我会用const代替var
菲利克斯·克林

5
@FelixKling,“我假设您知道您的代码无论如何都不会这样做。” -这个说法很不好。否则,毫无意义const
Meandre '16

Answers:


249

所做的事情没有问题,但是您必须记住函数声明和函数表达式之间的区别。

一个函数声明,即:

function doSomething () {}

完全吊在示波器的顶部(和类似的范围letconst它们也都在块范围内)。

这意味着以下将起作用:

doSomething() // works!
function doSomething() {}

一个函数表达式,即:

[const | let | var] = function () {} (or () =>

是创建一个匿名函数(function () {})和一个变量,然后将该匿名函数分配给该变量。

因此,围绕作用域内变量提升的通常规则-块作用域变量(letconst)不会提升undefined到其块作用域的顶部。

这表示:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

由于doSomething未定义,将失败。(它将抛出 ReferenceError

如果切换为使用var,则可以使用该变量的提升,但是它将被初始化为,undefined因此上面的代码块仍然无法工作。(这将在您调用它时抛出一个TypeError因为doSomething不是函数)

就标准做法而言,您应该始终使用适当的工具来完成这项工作。

Axel Rauschmayer在范围和吊装方面发表了出色的文章,包括es6语义:ES6中的变量和作用域


7
还要补充一点,es6类在内部使用const来保护类名,以防止在类内重新分配。
user2342460

1
a function a(){console.log(this);}b 之间一个微妙区别const a=_=>{console.log(this);}是,如果像这样调用它a.call(someVar);,在a中将打印someVar,在b中将打印window
前千

99

尽管使用const函数来定义似乎有点麻烦,但是它具有一些使它更加出色的优点(在我看来)

  1. 它使函数不可变,因此您不必担心该函数会被其他代码更改。

  2. 您可以使用短箭头语法,该语法较短且更简洁。

  3. 使用箭头功能可以this帮助您进行绑定。

举例 function

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

与相同的例子 const

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged


1
并且您可以两次声明函数add(x,y),但不能两次声明const add = ...
TatianaP

33
1.不变性是真正的好处,但是很少有人真正覆盖一个函数。2.除非您的函数可以是表达式,否则短箭头语法不会更短。function f(x, y) {是18个字符,const f = (x, y) => {是21个字符,因此长3个字符。3.仅当函数在方法(或其他有意义的函数)中定义时,保持此绑定才重要。在顶级脚本中,它毫无意义。我并不是说您错了,只是您提到的原因并不十分相关。
赤裸裸的

@Nakedible那么还有哪些其他有效原因?
阿尼斯·拉马斯瓦米

13
老式函数语法的一个优点是在调试过程中有一个名称。
user949300 18-10-27

3
我将使用linters来防止重新绑定函数声明。
富兰克林·于

31

问这个问题已经三年了,但是我现在遇到了这个问题。由于此答案离堆栈很远,请允许我重复一下:

问:我想知道在JavaScript中使用const可以设置哪种类型的值(特别是函数)是否有任何限制。这有效吗?当然可以,但是出于某种原因,它是否被视为不良做法?

我的动机是一个观察后做一些研究,多产的JavaScript编码谁总是使用const语句functions,即使没有明显的理由/效益。

在回答“ 是否出于任何原因被认为是不好的做法吗? ”,IMO,是的,或者至少使用声明有好处function

在我看来,这在很大程度上取决于偏好和风格。上面提供了一些很好的论据,但没有一个像本文中所讲的那么清楚:

持续的困惑:为什么我仍然使用 medium.freecodecamp.org/Bill Sourour,JavaScript专家,顾问和老师编写的JavaScript函数语句

我敦促每个人都阅读该文章,即使您已经做出决定。

这里是要点:

与[const]函数表达式相比,函数语句有两个明显的优点:

优势1:明确意图

每天扫描成千上万行代码时,尽可能快速,轻松地弄清程序员的意图很有用。

优势2:声明顺序==执行顺序

理想情况下,我希望按照我期望代码将被执行的顺序或多或少地声明我的代码。

这对我来说是最重要的:使用const关键字声明的任何值都无法访问,直到执行为止。

我上面刚刚描述的内容迫使我们编写看起来颠倒的代码。我们必须从最低级别的功能开始,然后逐步提高。

我的大脑不能那样工作。我想先了解一下背景信息。

大多数代码是由人类编写的。因此,大多数人的理解顺序大致遵循大多数代码的执行顺序是有道理的。


1
您可以对意图的清晰度发表更多评论吗?我得到#2,但据我所知#1只是#2的(预?)重复。我可以想到一种情况,即,将具有自己的defaultErrorHandlerconst的函数分配为匿名函数,然后可以从promise处理程序中调用它。这将使我能够根据需要选择“覆盖”函数中的默认错误处理程序。有些只需要返回一个错误对象,而另一些则需要返回http响应,从而使详细程度有所不同。但是无论如何,代码结构都可以是熟悉的模式。
杰克T.

也许我的想法太复杂了!只是将我的脑袋围绕着一些新方法,还没有花很多时间来实施它们。只是发现我真的.then( res.success, res.error )比我声明要调用的匿名函数好得多res.success(value);。具有.then( ..., defaultErrorHandler)通用模式可能会很好,可以在顶层定义defaultErrorHandler函数,并const defaultErrorHandler = error => { ... }根据需要在函数范围内进行声明。
杰克T.18年

1
@JakeT。RE“您能对意图的清晰度发表更多评论吗?”。好吧,首先,那句话并不是我的意思,而是那篇文章的作者freecodecamp.org/Bill Sourour所写的。但这对我来说是真正的常识。如果我读到“明天的函数()”,那么我立即知道它是一个函数。但是,如果我读到“ const明天=()=>”,我会停下来一会儿,然后解析语法以最终确定,是的,这是一个函数。
JMichaelTX '18年

1
另一件事,如果我有别人写的长脚本,并且想查看所有功能,则可以对“功能”进行快速搜索以找到它们。甚至更好的是,我可以编写一个快速的JS RegEx来提取所有功能。IMO,“ const”语句仅用于不会更改的数据(不是函数)。
JMichaelTX '18年

10

使用它有一些非常重要的好处,const并且有些人说,由于它是经过深思熟虑和具有指示性的,因此应尽可能使用它。

据我所知,它是JavaScript中最具指示性和可预测性的变量声明,也是最有用的声明之一,因为它的约束程度。为什么?因为它消除了varlet声明可用的某些可能性。

当您阅读时,可以推断出什么const?您只需阅读const声明语句即可知道以下所有内容,并且无需扫描对该变量的其他引用:

  • 该值绑定到该变量(尽管其基础对象不是深度不变的)
  • 无法在其直接包含的块之外进行访问
  • 由于时间死区(TDZ)规则,在声明之前从未访问过绑定。

以下引用来自一篇文章,论述了let和的好处const。它还可以更直接地回答您有关关键字的限制/限制的问题:

制约因素,如所提供的letconst是使代码更容易理解的一种强有力的方式。尝试在编写的代码中尽可能多地产生这些约束。限制代码段含义的声明性约束越多,将来人类阅读,解析和理解一段代码就越容易和快捷。

当然,const声明比声明有更多规则var:块范围,TDZ,在声明时分配,无重新分配。而var语句仅表示函数作用域。但是,规则计数并不能提供很多见识。最好从复杂性的角度权衡这些规则:规则是增加还是减少复杂性?在的情况下const,块作用域的作用域比函数作用域的作用域更窄,TDZ意味着我们无需从声明中向后扫描作用域即可在声明之前发现用法,而赋值规则意味着绑定将始终保留相同的参考。

语句越受约束,一段代码就变得越简单。当我们在一条语句可能意味着什么的条件上增加约束时,代码的不可预测性就会降低。这是为什么静态类型的程序通常比动态类型的程序更易于阅读的最大原因之一。静态类型给程序编写者带来了很大的限制,但同时也给程序的解释方式带来了很大的限制,使程序代码更易于理解。

考虑到这些论点,建议您const在可能的情况下使用,因为这是使我们思考的可能性最小的语句。

资料来源:https : //ponyfoo.com/articles/var-let-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.