JS的高阶函数指可以接收另一个函数作为参数的函数。高阶函数是高能函数,为JS编程注入了超级能量。先来看看箭头函数中高阶函数长什么样子:
// 高阶函数 : 求两个数分别经过另一个函数运算后的结果之和
const add = (x1, x2, func) => func(x1) + func(x2);
// 函数 : 求x的平方
const square = (x) => x**2;
// 应用示例
const result = add(102, 34, square);
console.log(result); // 结果为 11560
函数 add() 接收三个参数,第一、二个参数即 x1、x2 为数值,第三个参数 func 为函数。这样的参数构造,使用一个或多个函数作为参数,使得编程的灵活性瞬间提升,围绕它只需设计功能函数然后作为高阶函数的参数使用,可简单实现任意所需功能。square() 函数就是一个功能函数,它只处理一个参数 x,算出并返回 x 的平方;该函数在我们调用 add() 高阶函数时做为第三个参数使用,add() 函数分别使用它对参数 x1 和 x2 进行运算,最后求出两个数被函数 square() 操作后的和并返回计算结果。
以上,高阶函数待操作的数值参数固定为两个,而在实际编程实践中需要经常处理不确定个数的待运算参数,该如何实现?
这首先需要用到函数的不定参数,即不确定传参个数,本质上是对剩余参数的处理范畴。剩余参数结构为 ...rest,其中的 rest 是参数集合名称,可以是任意合法的变量名,习惯上使用 args,来自 arguments(注:arguments 是传统JS函数数组对象,返回参数值,箭头函数并不支持,所以只能用 ...rest 剩余函数来处理不确定个数的参数);其次需要遍历剩余参数对象,可以用 for 等循环语句和 forEach JS内置高阶函数,或者,也可以像下例那样使用更为简单而强大的归约函数 reduce 来实现。看看改造后的 add() 函数:
// 高阶函数 : 求N个数分别经过另一个函数运算后的结果之和
const add = (func, ...args) => args.reduce((total, val) => total + func(val), 0);
// 函数 : 求x的平方
const square = (x) => x**2;
// 应用示例
const result = add(square, 2, 3, 4, 5, 6);
console.log(result); // 结果为 90
这里的 add() 函数和前例不同,第一个参数为函数 func,第二个参数为数值集合即 ...args,可以是任意个参数。必须注意,...args 为不确定个数的参数,是剩余参数,位置必须是后置,否则报错。改造后的 add() 函数,参与运算的数值参数可以是 0 个,可以是任意多个,多个数值参数时彼此之间用小角逗号隔开。
这就实现了箭头函数中高阶函数处理不定参数的功能。还可以进一步扩展,让函数可以同时接收数值和数值数组然后进行运算,这会让函数的功能更为强大。实现思路也简单:参数是数值时直接运算,是数组时视为不定参数,递归调用函数自身对之进行运算。扩展后的函数如下:
// 高阶函数 : 求N个数分别经过另一个函数运算后的结果之和
const add = (func, ...args) => {
return args.reduce( (total, val) => {
return total + (Array.isArray(val) ? add(func, ...val) : func(val));
}, 0);
}
// 上面函数可以写成一行
//const add = (func, ...args) => args.reduce((total, val) => total + (Array.isArray(val) ? add(func, ...val) : func(val)), 0);
// 函数 : 求x的平方
const square = (x) => x**2;
//应用示例
const result = add(square, 10, [1,33,102], 5);
console.log(result); // 结果为 11619
这样,add() 高阶函数既可以接收任意多的参数,参数还可以是数值和数组格式,数组还不限于一维数组,任意维数的数组都会得到递归处理。
【附】reduce() 归约函数是JS内置高阶函数中非常强大简约的函数,和 map()、forEach()、filter() 等同属一个阵营,感兴趣的朋友可以自行网查。