JavaScript中的匿名函数是否是一种不好的实践?

28

我读到过在JavaScript中使用匿名函数是不好的实践,因为它可能会让调试变得复杂,但我自己并没有看到这种情况。那么,在JavaScript中使用匿名函数真的是不好的实践吗?如果是,为什么?

我听说在JavaScript中使用匿名函数不好,因为它可能会让调试非常困难,但是我自己没有亲身经历过。那么,JavaScript中使用匿名函数是否真的不好呢?如果确实不好,那是为什么?

开发者工具和构建/模块策略自2010年以来已经取得了长足的进步.. Chrome / WebKit非常好,FireBug一般般但还算够用(同时给函数命名表达式可以帮助视觉化)。无论如何,考虑到它们被使用的次数之多,这是一个..可疑的公理,可能与一开始就过于“聪明”且难以遵循/调试的代码有关..因为我从未感受到调试“我的”代码时的痛苦;-) - user2864740
6个回答

22

我会稍微违背潮流,并提出匿名函数虽然被广泛使用,但实际上是不好的实践。

1) 匿名函数无法被重复使用。

2) 匿名函数没有名称,因此不能描述它们的功能,也就是说代码不具备自我说明性。

3) 无法在单元测试框架中孤立地对匿名函数进行测试。

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

我确实认为有些情况下匿名函数是最佳选择,但通常为了避免上述缺点,我几乎总是给我的函数命名。

通常来说,匿名函数变得越长,它们受益于具有名称的可能性就越大。


2
  1. 匿名函数和闭包可以被重复使用,每个函数都是值,可以分配给变量或作为函数参数提供 - 这只是在正确的级别/范围下公开函数对象的问题;
  2. 匿名函数(或函数表达式)可以被赋予显式名称,但在上下文中仍然是“匿名”的;
  3. 取决于测试什么,如何测试以及如何公开函数对象;
  4. 闭包/lambda 可以在“过于聪明”的情况下被滥用,但是即使使用最简单的过程代码语句,_糟糕的编码人员仍然是糟糕的编码人员_。
- user2864740
1
我对你在这里说的话感到困惑。如果你给一个函数命名并将其分配给一个变量,那么它不就不是匿名函数了吗?你能举个带有名称的匿名函数的例子吗? - bhspencer
但是那种广泛的观点往往会让人感到困惑并且不正确。考虑一下这个例子:[].forEach(function () {..}) - 这个函数一个它所绑定的名称。或者,同样地,这个还是“匿名”的吗 - var filter = function () { .. }?问题在于,“匿名”这个词是一个不太准确的术语。 - user2864740
2
我不同意。在你的例子中,传递给forEach函数的函数没有名称。 - bhspencer
1
我同意当后来使用时它会被分配一个名称,但是在创建的上下文中它没有名称。正是在创建的上下文中,我的上述四点才成立。 - bhspencer
显示剩余3条评论

9

不,匿名函数在整个网络的JavaScript中得到了广泛应用。虽然这可能会使调试变得有些困难,但远远不足以说它们不应该被使用。

例如,JQuery广泛使用匿名函数。

有很多时候你想要使用它们而不是正式声明的函数,比如当你想要限制它们的范围时。


13
实际上,这是我停止使用jQuery的一个原因。它花费的时间总是比我认为合理的要长得多,以确定错误是我的代码中的语法错误、逻辑错误还是jQuery本身的问题。你必须承认,一堆匿名函数的调用栈并不能像命名函数那样清晰易懂。 - Kev
6
你可以始终使用命名函数表达式 - Marcel Korpel

8
我认为相反,Lambda(又名)使某些表达式更加简洁。如果您要将多个事件处理程序绑定到多个事件,则为每个事件处理程序都命名函数名称将很繁琐。
即使它使调试有点困难,但与不使用相比,它更有帮助和节省时间,而我很少因为函数是匿名的而苦于调试。编码时应使用JSLint使生活更轻松。

5

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

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


3
你可以始终使用一个具名函数表达式 - Marcel Korpel
1
@MarcelKorpel:你提供的链接已经失效了,但我猜你的意思是你可以选择给匿名函数添加一个名称(使其不再是匿名的),就像这样:var fAnonymous = (function nonAnon(){ });。这肯定有助于调试。 - palswim
@palswim 确实。值得一提的是,我链接的文章现在已经在Kangax的Github.io网站上了。 - Marcel Korpel

3
绝对不是,lambda函数被广泛应用于各个领域,几乎无处不在。

27
某件事情“常见”并不意味着它是“正确的”。使用匿名函数可能没有错,但说“每个人都这么做”并不能构成有效的论据。 - Ian Dunn
深度嵌套的Sass到处都是,但完全是错误的。 - Toni Leigh

0

这是我的浏览器控制台:

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

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

想象你在调试某些东西,有一个名为 groupy 的函数。你输入它的名称以获取更多信息。如果该函数已被设置为在坏部分中,则您无法知道原始声明是什么。然而,如果您像好部分一样定义函数名称,则始终会保留原始函数名称的跟踪。

2
如果你使用描述示例中函数的标识符,而不是传统的 "foo" 和 "bar" 标识符,那么你的答案会更清晰。在第三个押韵后,我的眼睛变得模糊了。 - Wes Modes
上面的评论是正确的,但这并不意味着原帖的回答是错误的。 - knickum
@knickum只是提出了一个问题,我没有看到答案。我特别回应了OP提到他们在使用匿名函数进行调试时没有遇到问题的这一点。如果您可以传递一个函数,它可以在任何地方被调用,在堆栈跟踪中调试具有函数名称的内容比没有更好一百万倍,因为在这种情况下您将没有其他定位它的方式。 - unflores
@WesModes 哎呀,也许我不应该选择押韵...但是函数的功能(嘿嘿)并不重要,真正重要的是名称是否显示。 - unflores
我将@unflores 称为OP,因为你的回答引发了这个评论线程。所以我同意另一个评论者(Wes Modes)的观点,即押韵并没有帮助,但我也要说这并不意味着你的回答是错误的。 - knickum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接