匿名函数在 JavaScript 中是一种不好的做法吗?

Posted

技术标签:

【中文标题】匿名函数在 JavaScript 中是一种不好的做法吗?【英文标题】:Are anonymous functions a bad practice in JavaScript? 【发布时间】:2011-03-28 14:18:28 【问题描述】:

我读到在 javascript 中使用匿名函数是不好的做法,因为它会使调试变得痛苦,但我自己还没有看到这一点。 JavaScript 中的匿名函数真的是不好的做法吗?如果是,为什么?

【问题讨论】:

自 2010 年以来,开发工具和构建/模块策略已经取得了漫长的发展。Chrome / WebKit 非常好,FireBug 一般但足够(并命名函数表达也可以在视觉上有所帮助)。无论如何,考虑到它们被使用的绝对次数,这是一个..可疑的公理,可能与“太聪明”并且难以遵循/调试的代码有关..因为我从来没有感觉到调试的痛苦我的代码;-) 【参考方案1】:

我将在这里稍微逆流而上,并说明匿名函数确实是不好的做法,即使它们被广泛使用。

1) 匿名函数不能重用。

2) 根据定义,匿名函数没有名称,因此不描述它们的作用。也就是说,代码不是自我记录的。

3) 匿名函数不能单独使用单元测试框架进行测试。

4) 我个人认为它们使代码更难阅读和调试。虽然您的体验可能会有所不同。

我确实认为在某些情况下匿名函数是最好的选择,作为一般规则,为了避免上述缺点,我几乎总是为我的函数命名。

通常,您的匿名函数越长,它就越有可能从拥有名称中受益。

【讨论】:

1) 匿名函数和闭包可以重复使用,每个函数都是值,可以分配给变量或作为函数参数提供 - 这只是公开函数对象的问题,例如正确的级别/范围; 2) 匿名函数(或函数表达式)可以给出明确的名称,但在上下文中是“匿名的”; 3)取决于测试什么,如何测试,以及函数对象如何暴露; 4) 闭包/lambda可以在“太聪明”的情况下被滥用,但是糟糕的编码员就是糟糕的编码员,即使是最琐碎的程序代码语句.. 你在这里说的话让我很困惑。如果您给一个函数一个名称并将其分配给一个变量,那么根据定义它不是匿名函数吗?你能举个匿名的例子吗? 问题是“匿名”函数这个词是个谎言。真正的术语应该是 function expressionclosure 甚至 lambda (这与***“函数语句”或“方法”不同) .因为如何使用“匿名”函数(IIFE 除外)而没有 some 名称? 我不同意。在您的示例中,传递给名为 forEach 的函数的函数没有名称。 我同意它在以后使用时被分配了一个名称,但它在创建它的上下文中没有名称。它是在我的 4上面列出的要点。【参考方案2】:

不,匿名函数在 Web 上的 JavaScript 中随处可见。它可能会在某些地方使调试变得更加困难,但还不足以说不应该使用它们。

例如,JQuery 广泛使用它们。

很多时候你想在正式声明的函数上使用它们,例如当你想限制它们的范围时。

【讨论】:

实际上,这是我停止使用 jQuery 的原因之一。确定一个 bug 是我的代码中的语法错误、我的代码中的逻辑错误还是 jQuery 本身的问题,花费的时间总是比我认为合理的要长得多。您必须承认,匿名函数的调用堆栈并不像命名函数那样使事情一目了然。 您可以随时使用named function expression。【参考方案3】:

我会说相反,lambdas ( alias ) 使一些表达式更加简洁。例如,如果您将多个事件处理程序绑定到多个事件,那么为每个事件处理程序指定一个函数名称会很乏味。

它比没有更有用和更节省时间,即使它使调试有点困难,但我很少为调试而苦恼,因为函数是匿名的。并且你应该使用 JSLint 来让你在编码时更轻松。

【讨论】:

【参考方案4】:

绝对不是,lambda 函数在无处不在,几乎无处不在。

【讨论】:

某事常见并不意味着它是正确。使用匿名函数可能没有错,但是说“每个人都这样做”并不构成有效的论据。 深嵌套的sass到处都是,但完全错了【参考方案5】:

仅仅因为每个人都使用它们并不能使它们成为良好的实践(每个人都记得使用 table 元素进行布局吗?)。但是,它们很棒,因为它们可以帮助澄清和简化您的代码,减少出错的机会。

但是,匿名函数不应该太复杂以至于调试变得困难。在这种情况下,也许最好创建一个新函数。

【讨论】:

您可以随时使用named function expression。 @MarcelKorpel:您提供的链接已经失效,但我认为您的意思是您可以选择为您的匿名函数添加一个名称(使其不再匿名),如下所示:var fAnonymous = (function nonAnon() );。这肯定有助于调试。 @palswim 确实如此。作为记录,我链接的文章现在在Kangax' site on Github.io。【参考方案6】:

这是我的浏览器控制台:

// Bad
poopy = function()
// function ()
groupy = poopy;
// function ()

// Good
droopy = function loopy();
// function loopy()
floupy = droopy;
// function loopy()   

假设您正在调试某些东西并且您有一个名为groupy 的函数名称。您键入它的名称以获取有关它的更多信息。如果该函数已在 bad 部分中设置,则您不知道原始声明是什么。但是,如果您在 Good 部分中定义了函数名称,那么您将始终可以找到原始函数名称。

【讨论】:

如果您在示例中使用描述其功能的标识符,而不是经典的foobar 标识符,您的答案会更加清晰。第三首韵后我的眼睛呆滞了。 以上评论是正确的,但它不会使OP的答案错误 @knickum Op 只有一个问题....我没有看到答案。我特别回应了 OP 提到他们没有看到使用匿名函数进行调试的问题。如果你可以传递一个函数,它就可以在任何地方被调用,调试一个包含函数名的堆栈跟踪比不这样做要好一百万倍,因为在这种情况下你将没有任何其他方法来定位它。跨度> @WesModes 呃,也许我不应该押韵……但是函数的功能(呵呵)并不重要,这完全是关于名称是否显示。 我将@unflores 称为 OP,因为正是您的回答启动了此评论线程。所以我同意另一位评论者(Wes Modes)的观点,即押韵没有帮助,但我也说这不会让你的答案出错。

以上是关于匿名函数在 JavaScript 中是一种不好的做法吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥向下转换在 C++ 中是一种不好的做法,而不是在另一种语言中呢? [关闭]

JavaScript:动态扩展原型是一种不好的做法吗?

重学JavaScript之匿名函数

JavaScript自定义函数进阶(匿名函数变量的作用域)

JavaScript自定义函数进阶(匿名函数变量的作用域)

js中的匿名函数和匿名自执行函数