JS箭头函数之高阶函数及其处理不定参数
<style>.artBox { font-size: 18px; margin: 20px auto; max-width: 1200px; }
.artBox > p { margin: 10px 0; line-height: 30px; }
.artBox mark { padding: 4px 6px; background: lightblue; }
</style>
<div class="artBox">
<p>JS的高阶函数指可以接收另一个函数作为参数的函数。高阶函数是高能函数,为JS编程注入了超级能量。先来看看箭头函数中高阶函数长什么样子:</p>
<div class="codebox">
<txt-green>// 高阶函数 : 求两个数分别经过另一个函数运算后的结果之和</txt-green>
const add = (x1, x2, <txt-blue>func</txt-blue>) => <txt-blue>func</txt-blue>(x1) + <txt-blue>func</txt-blue>(x2);
<txt-green>// 函数 : 求x的平方</txt-green>
const square = (x) => x**2;
<txt-green>// 应用示例</txt-green>
const result = add(102, 34, <txt-blue>square</txt-blue>);
console.log(result); <txt-green>// 结果为 11560</txt-green>
</div>
<p>函数 add() 接收三个参数,第一、二个参数即 x1、x2 为数值,第三个参数 func 为函数。这样的参数构造,使用一个或多个函数作为参数,使得编程的灵活性瞬间提升,围绕它只需设计功能函数然后作为高阶函数的参数使用,可简单实现任意所需功能。square() 函数就是一个功能函数,它只处理一个参数 x,算出并返回 x 的平方;该函数在我们调用 add() 高阶函数时做为第三个参数使用,add() 函数分别使用它对参数 x1 和 x2 进行运算,最后求出两个数被函数 square() 操作后的和并返回计算结果。</p>
<p>以上,高阶函数待操作的数值参数固定为两个,而在实际编程实践中需要经常处理不确定个数的待运算参数,该如何实现?</p>
<p>这首先需要用到函数的不定参数,即不确定传参个数,本质上是对剩余参数的处理范畴。剩余参数结构为 <mark>...rest</mark>,其中的 rest 是参数集合名称,可以是任意合法的变量名,习惯上使用 args,来自 arguments(注:arguments 是传统JS函数数组对象,返回参数值,箭头函数并不支持,所以只能用 ...rest 剩余函数来处理不确定个数的参数);其次需要遍历剩余参数对象,可以用 for 等循环语句和 forEach JS内置高阶函数,或者,也可以像下例那样使用更为简单而强大的归约函数 reduce 来实现。看看改造后的 add() 函数:</p>
<div class="codebox">
<txt-green>// 高阶函数 : 求N个数分别经过另一个函数运算后的结果之和</txt-green>
const add = (func, ...args) => args.reduce((total, val) => total + func(val), 0);
<txt-green>// 函数 : 求x的平方</txt-green>
const square = (x) => x**2;
<txt-green>// 应用示例</txt-green>
const result = add(<txt-blue>square</txt-blue>, 2, 3, 4, 5, 6);
console.log(result); <txt-green>// 结果为 90</txt-green>
</div>
<p>这里的 add() 函数和前例不同,第一个参数为函数 func,第二个参数为数值集合即 ...args,可以是任意个参数。必须注意,...args 为不确定个数的参数,是剩余参数,位置必须是后置,否则报错。改造后的 add() 函数,参与运算的数值参数可以是 0 个,可以是任意多个,多个数值参数时彼此之间用小角逗号隔开。</p>
<p>这就实现了箭头函数中高阶函数处理不定参数的功能。还可以进一步扩展,让函数可以同时接收数值和数值数组然后进行运算,这会让函数的功能更为强大。实现思路也简单:参数是数值时直接运算,是数组时视为不定参数,递归调用函数自身对之进行运算。扩展后的函数如下:</p>
<div class="codebox">
<txt-green>// 高阶函数 : 求N个数分别经过另一个函数运算后的结果之和</txt-green>
const add = (func, ...args) => {
return args.reduce( (total, val) => {
return total + (Array.isArray(val) ? add(func, ...val) : func(val));
}, 0);
}
<txt-green>// 上面函数可以写成一行</txt-green>
<txt-green>//const add = (func, ...args) => args.reduce((total, val) => total + (Array.isArray(val) ? add(func, ...val) : func(val)), 0);</txt-green>
<txt-green><txt-green>// 函数 : 求x的平方</txt-green></txt-green>
const square = (x) => x**2;
<txt-green>//应用示例</txt-green>
const result = add(square, 10, , 5);
console.log(result); <txt-green>// 结果为 11619</txt-green>
</div>
<p>这样,add() 高阶函数既可以接收任意多的参数,参数还可以是数值和数组格式,数组还不限于一维数组,任意维数的数组都会得到递归处理。</p>
<p>【附】reduce() 归约函数是JS内置高阶函数中非常强大简约的函数,和 map()、forEach()、filter() 等同属一个阵营,感兴趣的朋友可以自行网查。</p>
</div>
<script type="module">
import linenumber from 'https://638183.freep.cn/638183/web/js/linenumber.js';
linenumber();
</script> 最后的数组那里不太明白,如果不是数组,这样的独立的5个数字,结果也11619,不明白有这个数组有什么用呢。 函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了。 红影 发表于 2025-11-28 23:17
函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了 ...
数组的应用就大了去了。简单举个栗子:
假设从Excel中获取一行或一列数据,可以将数据做成数组,多行或多列也可以做成多个数组,这些数组都是由变量名代替入参,无需一整串数字入参。这样计算多少行多少列的数据都是个简单的事情。
复杂的栗子还有:一些表格是有单元格细分的,它们就是子数组或子子数组,转化为JS数组时就是一维数组或多维数组,这样,用多个数组入参进行运算会非常方便。
虽然JS函数支持多个参数,但习惯上,除非迫不得已,应尽量减少参数,默认标准的最多六个参数。数组可以解决这些问题。 红影 发表于 2025-11-28 23:17
函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了 ...
是的。不定参数视为剩余参数,rest,剩下的,所以只能放在后面,这是规范。 马黑黑 发表于 2025-11-28 23:27
数组的应用就大了去了。简单举个栗子:
假设从Excel中获取一行或一列数据,可以将数据做成数组,多行 ...
嗯嗯,用 Excel 举例就非常清楚了,一类的归到一个数组里,就不用给这些数字一个个设置参数了。
理解了数组,字数组不过是层级问题了。谢谢黑黑{:4_187:} 马黑黑 发表于 2025-11-28 23:28
是的。不定参数视为剩余参数,rest,剩下的,所以只能放在后面,这是规范。
嗯嗯,规范必须要记一下的。 红影 发表于 2025-11-29 09:00
嗯嗯,规范必须要记一下的。
这个必须,记两三下都不为过 红影 发表于 2025-11-29 08:53
嗯嗯,用 Excel 举例就非常清楚了,一类的归到一个数组里,就不用给这些数字一个个设置参数了。
理解了 ...
JS或其他语言的数组、对象,都是极好的存储数据的容器,也便于数据交流交换 第一次看到:以另一个函数作为参数的JS的高阶函数。谢谢马老师讲授{:4_191:} 杨帆 发表于 2025-11-29 19:08
第一次看到:以另一个函数作为参数的JS的高阶函数。谢谢马老师讲授
高阶函数不是JS独有,其它编程语言也有 马黑黑 发表于 2025-11-29 20:16
高阶函数不是JS独有,其它编程语言也有
又长见识了,谢谢马老师{:4_190:} 杨帆 发表于 2025-11-29 21:52
又长见识了,谢谢马老师
{:4_190:}
页:
[1]