为什么将大型匿名函数作为参数传递给其他函数,从而在JavaScript中得到如此广泛的接受?


27

我有一个观点(我肯定会与某些人共享),因为传递包含多行代码的匿名函数,因为其他函数的参数会极大地影响可读性和自我文档编制,以至于我认为对于任何可能使用该代码仅声明一个命名函数的人来说,它都要好得多。或者至少在声明函数之前将该匿名函数分配给变量

但是,许多JavaScript库(jQuery,d3.js / NVD3.js)仅举几个例子,就以这种方式使用大型函数。

为什么这在JavaScript中如此广泛地被接受?它是一种文化的东西,还是我缺少的优势,这将使使用它比声明命名函数更可取?


1
这可能与使用闭包有关。这也可能与不想向外部公开实际功能(这就是为什么它是匿名的)有关。
罗伯特·哈维

3
@RobertHarvey换句话说,这是JavaScript不具有publicprivate的一种解决方法?
梅森惠勒

2
在许多地方,大型匿名函数读起来更像是一个块,一旦习惯了,通常感觉就很不错。作用域规则甚至还支持块状感觉。

5
@MasonWheeler:这取决于您的观点。一个计划或ECMAScript的程序员可能会说,public并且private是没有正确关闭的解决方法。
约尔格W¯¯米塔格

1
@JörgWMittagHooray for Racket,XKCD 927
梅森惠勒

Answers:


23

我能想到的三个主要原因:

  1. 父范围访问
  2. 隐私
  3. 减少较高范围中定义的名称

父作用域访问:内联函数定义允许内联代码访问父作用域中定义的变量。这对许多事情都非常有用,并且如果正确完成的话,可以减少代码的数量或复杂性。

如果将代码放入此范围之外定义的函数中,然后调用该代码,则必须传递要访问该函数的任何父状态。

隐私:内联匿名定义中的代码更具私密性,其他代码无法调用。

减少在较高作用域中定义的名称: 在全局作用域中操作时,这是最重要的,但是内联匿名声明使您不必在当前作用域中定义新的符号。由于Javascript本身并不要求使用名称空间,因此避免定义比最低要求更多的全局符号是明智的。


社论:在Javascript中似乎已经成为一种文化,在这种情况下,即使不使用父级作用域访问,以某种方式声明匿名内联比定义一个函数并调用它也被认为“更好”。我怀疑这最初是由于Javascript中的全局名称空间污染问题,然后可能是由于隐私问题。但是现在它已变成某种文化上的东西,您可以看到它在许多公共代码机构中表达(如您提到的代码)。

在像C ++这样的语言中,大多数人可能会认为拥有一个跨多个页面/屏幕的巨大功能不是一种理想的做法。当然,C ++具有内置的命名空间,不提供父范围访问,并且具有隐私功能,因此它可以完全由可读性/可维护性来激发,而Javascript必须使用代码表达式来实现隐私和父范围访问。因此,JS似乎是朝着不同的方向发展的,即使在特定情况下不需要激发该方向的事物,它在语言中也已成为一种文化事物。


作为一名C ++开发人员,最近在我的很多工作中转而使用JS,这个答案很有道理,尤其是“父级范围访问”点-它确实具有极大简化代码的能力。一个nitpick-C ++确实在C ++ 11 lambdas中提供了父作用域访问:)但是绝对是+1。
指挥官香菜Sal 2016年

8

与大多数语言相比,JavaScript中使用匿名函数的目的更多。

首先,它们用于命名空间和块作用域。直到最近,JavaScript仍缺乏模块或任何其他种类的命名间隔机制,导致使用匿名函数通过模块模式来提供该功能。命名这些功能绝对没有任何好处。在较小的规模上,由于JavaScript 直到最近才缺少块作用域,因此使用了类似的模式来模拟块作用域。最明显的是在循环体内。在这种情况下,使用命名函数会产生混淆。

其次,匿名函数通常与模仿JavaScript的高阶函数一起使用,而JavaScript的特定性较低,它们通常与控件结构一起使用。例如,jQuery的each方法。我怀疑您是否将每一个循环体或if分支抽象到一个函数中,只要它的长度超过几行。在这种情况下,适用相同的逻辑。

最后一个原因是基于事件的编程在JavaScript中很常见,这往往会导致不经意的延续传递样式代码。您进行一个AJAX调用并注册一个回调,该回调在执行时将进行另一个AJAX调用并注册一个回调等。如果调用是同步的而不是异步的,那么这将是单个词法范围内的直线代码序列。同样,我怀疑您会将直线代码的每几行抽象为一个函数。

还有文化因素,并且由于上述原因,匿名函数在JavaScript中比许多其他语言更常见,并且比许多其他语言更舒适/更轻松地使用。


我自己的C ++编码中可能幼稚的结构有时采用了基于事件的编码原理,并通过std :: function和lambdas从JavaScript进行回调。就我而言,部分原因是我在用C ++编写UI代码并且不想执行阻塞操作。我很好奇JavaScript的实践是否对任何人都有用,只要该语言能很好地支持它们。
Katana314 '16
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.