函数是JavaScript中的第一等公民。这就是为什么你很早就会听到JavaScript中的回调函数,它是编写JavaScript代码时的一个超级强大的资产。在这里,我想给大家简单介绍一下它们。
回调函数通常作为参数传递给函数:
function printText(text, fn) {
...
}
printText('do something', function printSomethingElse() {
console.log('do something afterward');
});
在这个例子中,我们的printText 函数需要两个参数:一个文本和一个回调函数。回调函数是作为一个内联函数传递给printText 。你也可以在传递给printText 之前,将其作为一个函数声明提取:
function printText(text, fn) {
...
}
function printSomethingElse() {
console.log('do something afterward');
}
printText('do something', printSomethingElse);
这两种方式都可以。现在,不管我们传递给printText 函数的文本是什么,我们希望最终在我们的printText 函数中的某个地方执行回调函数,因为否则我们就不会把它传递进去:
function printText(text, fn) {
console.log(text);
fn();
}
function printSomethingElse() {
console.log('do something afterward');
}
printText('do something', printSomethingElse);
这可能是接收我们回调函数的printText 函数的一种实现方式。在这种情况下,它将首先打印*"做某事",然后"之后做某事"*。你如何实现所有这些函数,完全取决于你。这更多的是关于作为参数传递给printText 函数的函数,以及在这个函数中用于在某个点上被调用。
从本质上讲,一个回调函数被用于另一个函数中,最终被执行。这个另一个函数决定什么时候执行这个函数,以及它向这个函数传递哪些参数。
例如,让我们创建一个通用的过滤器函数,根据一个回调函数过滤一个JavaScript数组:
function filter(list, filterFn) {
let newList = [];
for (let i = 0; i < list.length; i++) {
const item = list[i];
if (filterFn(item)) {
newList.push(item);
}
}
return newList;
}
该函数接收一个数组作为第一参数,接收一个回调函数作为第二参数。当函数本身在数组上迭代时,它拉出数组中的每一个项目并将其传递给回调函数。如果回调函数返回true,则该项目被添加到过滤的列表中。如果回调函数返回false,它就不会被添加到过滤后的列表中。
这里最关键的一点是,过滤器函数不知道任何用于将项目添加到列表中的条件。它只知道它根据来自外部的一些条件(回调函数)来过滤一个数组。现在,我们可以通过以下方式使用这个通用的过滤函数:
const result = filter([3, 6, 1], function greaterThanFive(item) {
return item > 5;
});
console.log(result);
// [6]
如前所述,你可以把回调函数作为参数内联,也可以在外部声明它:
function greaterThanFive(item) {
return item > 5;
}
const result = filter([3, 6, 1], greaterThanFive);
console.log(result);
// [6]
重要的事实是,作为使用过滤函数的开发者,我们决定在这里应用哪个过滤条件。从这里开始,使用JavaScript的内置过滤器就不远了,它可以在JavaScript数组上使用:
const result = [3, 6, 1].filter(function greaterThanFive(item) {
return item > 5;
});
console.log(result);
// [6]
这个函数的行为和我们之前自己实现的一样,因为它需要一个回调函数,这个回调函数也会评估过滤条件。唯一不同的是,它已经作为一个方法内置在JavaScript数组中了。
对于所有这些情况,你也可以使用匿名的JavaScript回调函数,如果它们是内联的:
const result = [3, 6, 1].filter(function (item) {
return item > 5;
});
此外,你还可以使用JavaScript箭头函数,以保持你的回调函数更加简洁:
const result = [3, 6, 1].filter((item) => item > 5);
console.log(result);
// [6]
总之,回调函数很强大。以回调函数为参数的函数可以保持相当的通用性,因为使用这个函数的开发者必须在回调函数中定义关键行为。