为什么要将整个函数定义作为参数传递,而不仅仅是可以重用的函数名称?

Why pass an entire function definition as an argument instead of just the function name which can be reused?

前者好像比JavaScript多"hip",不明白为什么。

编辑:针对这个可能重复的问题,我感兴趣的是为什么,而不是如何。另一个仅在标题中询问 "closures" 的问题不会引起尚未在此和闭包之间做出 link 的人的注意。

tl;dr:因为很多函数其实并没有被复用


我想你已经回答了你自己的问题:

... instead of just the function name which can be reused?

其中许多是 "one-off" 个案例。该行代码只执行一次,传递的函数不必重复使用。

例如,如果我想将一个事件处理程序绑定到一个 body 并且我不打算在任何地方重用该事件处理程序,我为什么要写

function bodyEventHandler() {}
document.body.addEventListener('click', bodyEventHandler);

并用 bodyEventHandler?

不必要地污染当前作用域
document.body.addEventListener('click', function() {...});

效果相同,不污染作用域,在使用的地方保留函数定义。

JavaScript 很大程度上是事件驱动的,大多数事件处理程序实际上不会在其他任何地方重用。


在使用函数的地方保留函数定义也是 IMO 的一个常见原因。有些功能要么很简单,但是给它们取一个描述性的名字可能并不容易。

例如如果你不熟悉"pluck"这个词,你会明白什么

var names = users.map(pluck('name'));

真的吗?也许你可以从其他变量名称中推断出来。

然而,

var names = users.map(function(user) { return user.name; });

一目了然。

事实上,你会更频繁地看到这些,现在 ECMAScript 6 引入了箭头函数,就像其他语言中的 lambda 函数一样:

var names = users.map(user => user.name);

我还认为您对传递函数时到底发生了什么有误解:

... pass an entire function definition as an argument instead of just the function name ...

foo(bar) 不会将名称 "bar" 传递给 foo。它传递由变量 bar 引用的函数对象。那和foo(function() { ... })没什么区别。唯一的区别是我们没有(暂时)将函数存储在变量中。