高阶函数指接收或返回函数的函数,如map、filter、reduce、addEventListener、setTimeout等;常见错误是传函数调用而非函数本身,如filter(n>10)应为filter(n=>n>10)。

map、filter、reduce、addEventListener、setTimeout —— 只要一个函数接收另一个函数当参数,或者返回一个函数,它就是高阶函数。这不是语法糖,是 JavaScript 把函数当“值”来用的底层能力。
哪些内置方法是高阶函数?怎么传参才不报错
最常踩坑的是把函数调用写成函数本身:filter(n > 10) 是错的,因为 n > 10 立即求值为 true 或 false,传进去的是布尔值,不是函数;正确写法是 filter(n => n > 10)。
-
map要求回调函数返回新值,签名是(item, index, array) => newValue -
filter回调必须返回boolean,且只保留true的项 -
reduce第一个参数是累加器函数(acc, current) => newAcc,第二个参数是初始值(不传时默认取数组首项) -
sort接收比较函数(a, b) => number,别漏掉return,否则默认返回undefined,排序乱序
自己写高阶函数:柯里化和记忆化怎么用才不翻车
柯里化本质是“返回函数”,适合固化配置;记忆化靠闭包缓存结果,但只对纯函数有效。
- 柯里化示例:
const add = x => y => x + y,add(5)(3)得8;可用于封装日志级别:const logError = withLevel('ERROR') - 记忆化要防副作用:如果被缓存的函数发请求或改状态,缓存结果可能过期
- 别对小参数盲目 memoize:比如
memoize(Boolean)或memoize(String.toLowerCase),Map查找开销可能比计算还重
为什么链式调用 .filter().map().reduce() 在大数据量下变慢
每次调用都生成一个新数组,三步就创建两个中间数组,内存和 GC 压力明显上升。
- 10 万条数据时,
arr.filter(...).map(...).reduce(...)比单次for...of多分配 20 万+ 元素空间 - 替代方案不是抛弃高阶函数,而是按需切换:逻辑简单、数据量大 → 用
for;逻辑复杂、数据量中等 → 保留链式,语义清晰更重要 - 想兼顾两者?可封装一个
pipe工具,把多个转换函数组合成一次遍历,但要注意调试难度会上升
事件和定时器也是高阶函数?那 var 循环里 setTimeout 为啥总输出同一个值
是的,addEventListener 和 setTimeout 都是典型的“接收函数”型高阶函数——它们不返回函数,但强制你传函数进去,否则直接报 TypeError: cb is not a function。
立即学习“Java免费学习笔记(深入)”;
- 陷阱:用
var声明循环变量i,所有setTimeout回调共享同一个i,最终全输出arr.length - 解法只有两个:
let i(块级作用域),或用立即执行函数捕获当前值:((i) => setTimeout(() => console.log(i), 100))(i) - 现代写法更推荐
Promise+async/await,但底层仍是高阶函数思想:把执行时机交给运行时,而不是你手动控制
debounce 或 memoize,而是在业务代码里识别出“行为可抽象”的节点——比如权限校验、错误统一处理、接口埋点。这些地方一旦用高阶函数抽出来,后续加功能就只是往管道里塞新函数,而不是翻旧代码改 if 分支。











