正确使用 const 定义函数

IT技术 javascript function constants ecmascript-6
2021-02-10 16:47:16

const在 JavaScript 中可以设置哪些类型的值,尤其是函数,是否有任何限制这是有效的吗?当然它确实有效,但是出于任何原因它被认为是不好的做法吗?

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

ES6 中的所有函数都应该这样定义吗?如果是这样的话,这似乎并没有流行起来。

5个回答

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

一个函数声明,即:

function doSomething () {}

完全提升到作用域的顶部(let并且const它们也是块作用域)。

这意味着以下内容将起作用:

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

一个函数表达式,即:

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

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

因此,在作用域内提升变量的通常规则——块作用域变量(letconst)不会提升undefined到它们的块作用域的顶部。

这意味着:

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

将失败,因为doSomething未定义。(它会抛出一个 ReferenceError

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

就标准做法而言,您应该始终使用适合工作的工具。

Axel Rauschmayer 发表了一篇关于作用域和提升(包括 es6 语义)的精彩博文:ES6 中的变量和作用域

只想补充一点,es6 类在内部使用 const 来保护类名不会在类内重新分配。
2021-03-17 16:47:16
a function a(){console.log(this);}b 之间一个细微差别const a=_=>{console.log(this);}是,如果你称它为a.call(someVar);,在a 中,它将打印someVar,在b 中,它将打印window
2021-03-24 16:47:16

虽然使用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

我会使用 linter 来防止重新绑定函数声明。
2021-03-22 16:47:16
1. 不变性是一个真正的好处,但很少有人真正覆盖一个函数。2. 除非您的函数可以是表达式,否则胖箭头语法并不短。function f(x, y) {是 18 个字符,const f = (x, y) => {是 21 个字符,所以长了 3 个字符。3. 只有在方法(或其他具有 this 意义的函数)中定义函数时,保持 this 绑定才重要。在顶级脚本中,它毫无意义。我并不是说你错了,只是你提到的原因并不是非常相关。
2021-03-29 16:47:16
@Nakedible - 我也更喜欢使用,function但在您的比较中,您忘记了function需求,return而另一种方法则没有。(除非我不知道捷径?)
2021-04-10 16:47:16
老式函数语法的一个优点是在调试期间它有一个名称。
2021-04-12 16:47:16

问这个问题已经三年了,但我现在才遇到它。由于这个答案在堆栈中太远了,请允许我重复一遍:

问:我感兴趣的是,对于在 JavaScript 中使用 const 设置的值的类型是否有任何限制——特别是函数。这是有效的吗?当然它确实有效,但是出于任何原因它被认为是不好的做法吗?

在观察了一位多产的 JavaScript 编码员后,我有动力去做一些研究,他总是使用const语句 for functions,即使没有明显的原因/好处。

回答“是否出于任何原因被认为是不好的做法? ”让我说,IMO,是的,或者至少,使用语句优势function

在我看来,这主要是偏好和风格的问题。上面提出了一些很好的论据,但没有像本文中所做的那样清楚:

持续困惑:为什么我仍然使用 JavaScript 函数语句由 medium.freecodecamp.org/Bill Sourour,JavaScript 大师、顾问和教师撰写。

我敦促每个人都阅读那篇文章,即使你已经做出了决定。

以下是要点:

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

优势一:意图清晰

每天扫描数千行代码时,能够尽可能快速、轻松地找出程序员的意图非常有用。

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

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

这对我来说是最重要的:任何使用 const 关键字声明的值在执行到达之前都是不可访问的。

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

我的大脑不是那样工作的。我想要细节之前的上下文。

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

@JMichaelTX - 我明白你所说的阅读function tomorrow() { }vs const tomorrow = () => { },但肯定这只是更习惯于看到一个而不是另一个的情况?一两天后,您应该适应能够发现新模式的能力......此外,如果您在搜索或正则表达式期间使用这些功能,替换function with 与) => {您一样好,甚至更好避免任何评论中碰巧有函数这个词。
2021-03-17 16:47:16
@杰克T。RE“您能否对意图的清晰度发表更多评论?”。好吧,首先,那句话不是我写的,而是那篇文章的作者 freecodecamp.org/Bill Sourour 写的。但这对我来说是真正的常识。如果我读到“函数明天()”,那么我立即知道它是一个函数。但是如果我读到“const明天=()=>”,我会停下来解析我脑海中的语法来最终确定,好吧,是的,它是一个函数。
2021-03-22 16:47:16
也许我的想法太复杂了!只是围绕着一些新的实践,还没有花费大量的时间来实施它们。只是发现我真的.then( res.success, res.error )比我宣布只调用的匿名函数更喜欢res.success(value);拥有一个.then( ..., defaultErrorHandler)通用模式可能很好,具有顶级定义的 defaultErrorHandler 函数,并且可以const defaultErrorHandler = error => { ... }根据需要在函数范围内声明一个。
2021-03-23 16:47:16
您能否对意图的明确性发表更多评论?我得到#2,但据我所知#1 只是#2 的(预?)重复。我可以想到一个案例,即具有自己的defaultErrorHandlerconst 分配为匿名函数的函数,然后我可以从Promise处理程序调用该函数。这将使我能够根据需要在函数中选择性地“覆盖”这个默认错误处理程序。有些只需要返回一个错误对象,而另一些则需要返回一个 http 响应,详细程度各不相同。然而,无论如何,代码结构可以是一种熟悉的模式。
2021-03-31 16:47:16
另一件事,如果我有一个由其他人编写的长脚本,并且我想查看所有函数,我可以快速搜索“函数”以找到它们。或者更好的是,我可以编写一个快速的 JS RegEx 来提取所有函数。IMO,“const”语句仅适用于不会更改的数据(而非函数)。
2021-04-12 16:47:16

使用 有一些非常重要的好处const,有些人会说应该尽可能使用它,因为它是多么深思熟虑和指示性。

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

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

  • 该值绑定到该变量(尽管它的底层对象不是非常不可变的)
  • 它不能在其直接包含的块之外访问
  • 由于临时死区 (TDZ) 规则,在声明之前永远不会访问绑定。

以下报价是从一篇文章争论的好处letconst它还更直接地回答了您关于关键字约束/限制的问题:

诸如由let提供的约束const是使代码更易于理解的强大方式。尝试在您编写的代码中尽可能多地增加这些约束。限制一段代码含义的声明性约束越多,未来人类阅读、解析和理解一段代码就越容易、越快。

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

约束语句越多,一段代码就越简单。当我们为语句的含义添加约束时,代码变得不那么不可预测了。这是静态类型程序通常比动态类型程序更易于阅读的最大原因之一。静态类型对程序编写者施加了很大的约束,但它也对程序的解释方式施加了很大的约束,使其代码更易于理解。

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

来源:https : //ponyfoo.com/articles/var-let-const

这个问题是关于functionvsconst不是varvs const而这个答案本身就表明,使用const来定义 afunction不是可读性增强,实际上是现代 JS 中的可读性回归。因为这个答案已经将它混淆为变量,而不是函数。
2021-03-13 16:47:16

有一些特殊情况arrow functions不会成功:

  1. 如果我们正在更改外部 API 的方法,并且需要对象的引用。

  2. 如果我们需要使用的是专用的特殊的关键字function表达式:argumentsyieldbind等欲了解更多信息: Arrow功能表达的局限性

例子:

我将此函数指定为HighchartsAPI 中的事件处理程序它由库触发,因此this关键字应匹配特定对象。

export const handleCrosshairHover = function (proceed, e) {
  const axis = this; // axis object
  proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // method arguments
};

使用箭头函数,this将匹配声明范围,我们将无法访问 API obj:

export const handleCrosshairHover = (proceed, e) => {
  const axis = this; // this = undefined
  proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // compilation error
};