高阶函数是接受函数作为参数或返回函数的函数,如map、filter、reduce;map生成新数组,filter按布尔判断筛选,reduce需谨慎设置初始值以避免错误。

高阶函数就是接受函数作为参数或返回函数的函数
JavaScript 里 map、filter、reduce 都是典型的高阶函数——它们本身是函数,而且必须传入一个函数(回调)才能工作。这不是语法糖,而是函数式编程的核心机制:把“做什么”和“怎么做”分离。比如 arr.map(fn) 不关心 fn 怎么实现,只负责按顺序调用它并收集返回值。
map 的关键不是遍历,而是生成新数组
map 的唯一职责是:对原数组每个元素调用一次回调,把每次返回值组成一个**长度相同的新数组**。它不修改原数组,也不会跳过空位(稀疏数组中 undefined 仍会触发回调)。
-
回调函数默认接收三个参数:
item、index、array,但多数场景只用第一个 - 如果回调返回
undefined或没写return,新数组对应位置就是undefined - 不能用
map替代forEach做纯副作用操作(比如发请求、改 DOM),因为它的设计意图是转换,不是执行
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2); // [2, 4, 6]
const withIndex = numbers.map((n, i) => `${i}:${n}`); // ['0:1', '1:2', '2:3']filter 的判断逻辑必须明确返回布尔值
filter 看似简单,但常见错误是误以为“真值”就代表“保留”。实际上它只认 true / false,其他值会被强制转布尔——而对象、非空字符串、非零数字都是真值,容易导致意外保留。
- 回调返回
true时保留当前项,false时丢弃 - 避免直接返回对象或数组:
arr.filter(item => item.profile)可能出错,应写成arr.filter(item => item.profile != null) -
filter不改变原数组,也不保证返回数组的引用是否复用(不要依赖 === 判断)
const users = [{id: 1, active: true}, {id: 2, active: false}, {id: 3}];
const activeUsers = users.filter(u => u.active === true); // 明确比较reduce 容易错在初始值和累加器类型不匹配
reduce 是最灵活也最容易出错的。核心问题在于:第一次调用回调时,累加器(accumulator)的值取决于是否传了初始值。没传时,它取数组第一个元素,回调从第二个开始执行;传了则从第一个开始。
立即学习“Java免费学习笔记(深入)”;
- 处理空数组时,**必须提供初始值**,否则抛
TypeError: Reduce of empty array with no initial value - 初始值类型要和预期返回值一致:求和用
0,拼接字符串用'',累积对象用{} - 别在回调里修改传入的初始对象(比如用
{}当初始值,又在里面直接赋值acc[key] = val),这会污染原对象
const nums = [1, 2, 3];
const sum = nums.reduce((acc, curr) => acc + curr, 0); // 正确:初始值 0
const grouped = nums.reduce((acc, n) => {
acc[n % 2 === 0 ? 'even' : 'odd'].push(n);
return acc;
}, { even: [], odd: [] }); // 初始值必须是完整结构实际写业务逻辑时,reduce 的可读性常不如链式调用 filter + map,除非你确实需要单次遍历完成聚合。三者嵌套时,注意执行顺序和中间数组创建开销——这不是性能瓶颈的主因,但过度嵌套会让调试变困难。










