马黑黑 发表于 2025-11-28 21:51

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>

红影 发表于 2025-11-28 23:11

最后的数组那里不太明白,如果不是数组,这样的独立的5个数字,结果也11619,不明白有这个数组有什么用呢。

红影 发表于 2025-11-28 23:17

函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了。

马黑黑 发表于 2025-11-28 23:27

红影 发表于 2025-11-28 23:17
函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了 ...

数组的应用就大了去了。简单举个栗子:

假设从Excel中获取一行或一列数据,可以将数据做成数组,多行或多列也可以做成多个数组,这些数组都是由变量名代替入参,无需一整串数字入参。这样计算多少行多少列的数据都是个简单的事情。

复杂的栗子还有:一些表格是有单元格细分的,它们就是子数组或子子数组,转化为JS数组时就是一维数组或多维数组,这样,用多个数组入参进行运算会非常方便。

虽然JS函数支持多个参数,但习惯上,除非迫不得已,应尽量减少参数,默认标准的最多六个参数。数组可以解决这些问题。

马黑黑 发表于 2025-11-28 23:28

红影 发表于 2025-11-28 23:17
函数 func的位置有讲究的,本来是放后面的,当遇到剩余参数,因为位置必须后置,所以这个时候它就在前面了 ...

是的。不定参数视为剩余参数,rest,剩下的,所以只能放在后面,这是规范。

红影 发表于 2025-11-29 08:53

马黑黑 发表于 2025-11-28 23:27
数组的应用就大了去了。简单举个栗子:

假设从Excel中获取一行或一列数据,可以将数据做成数组,多行 ...

嗯嗯,用 Excel 举例就非常清楚了,一类的归到一个数组里,就不用给这些数字一个个设置参数了。
理解了数组,字数组不过是层级问题了。谢谢黑黑{:4_187:}

红影 发表于 2025-11-29 09:00

马黑黑 发表于 2025-11-28 23:28
是的。不定参数视为剩余参数,rest,剩下的,所以只能放在后面,这是规范。

嗯嗯,规范必须要记一下的。

马黑黑 发表于 2025-11-29 12:07

红影 发表于 2025-11-29 09:00
嗯嗯,规范必须要记一下的。

这个必须,记两三下都不为过

马黑黑 发表于 2025-11-29 12:08

红影 发表于 2025-11-29 08:53
嗯嗯,用 Excel 举例就非常清楚了,一类的归到一个数组里,就不用给这些数字一个个设置参数了。
理解了 ...

JS或其他语言的数组、对象,都是极好的存储数据的容器,也便于数据交流交换

杨帆 发表于 2025-11-29 19:08

第一次看到:以另一个函数作为参数的JS的高阶函数。谢谢马老师讲授{:4_191:}

马黑黑 发表于 2025-11-29 20:16

杨帆 发表于 2025-11-29 19:08
第一次看到:以另一个函数作为参数的JS的高阶函数。谢谢马老师讲授

高阶函数不是JS独有,其它编程语言也有

杨帆 发表于 2025-11-29 21:52

马黑黑 发表于 2025-11-29 20:16
高阶函数不是JS独有,其它编程语言也有

又长见识了,谢谢马老师{:4_190:}

马黑黑 发表于 2025-11-29 22:03

杨帆 发表于 2025-11-29 21:52
又长见识了,谢谢马老师

{:4_190:}
页: [1]
查看完整版本: JS箭头函数之高阶函数及其处理不定参数