JavaScript数组遍历方法差异显著:forEach纯副作用执行、map结构守恒投影、filter布尔筛选、reduce累加器状态机,性能for最快但语义准确性优先。

JavaScript 数组遍历方法看似相似,实则底层逻辑、执行契约和适用边界差异显著。选错方法不仅影响可读性,还可能引入空位处理异常、初始值陷阱或性能浪费。
forEach:纯副作用执行器,不返回也不中断
它本质是「带索引的 for 循环封装」,只保证按序调用回调,不做任何结果收集。不返回值(永远是 undefined),也不允许 break 或 return 跳出循环——哪怕回调里写 return,也只是退出当前迭代,下一项仍会执行。
- 跳过稀疏数组中的空位(
i in array为 false 的索引),但不触发 getter/setter - this 绑定需显式传入第二个参数,否则默认为
undefined(严格模式下) - 适合 DOM 批量操作、日志打印、状态收集等无返回需求场景
map:结构守恒的投影操作,空位保留但元素可变
它不是简单“循环+push”,而是严格维持原数组长度和索引结构:对每个存在的索引调用回调,生成新数组对应位置的值;空位被跳过,但新数组该位置仍是空位(不是 undefined,是真正缺失)。
- 返回新数组,长度恒等于原数组
length - 不能用
array[i] !== undefined判断是否存在,得用i in array——否则0、false等合法 falsy 值会被误判为空 - 适合字段提取、数值转换、对象结构重塑等需要一一映射的场景
filter:布尔驱动的筛选器,空位不跳但结果长度不定
判定依据是回调返回值经 Boolean() 强制转换后的真假,不是字面量 true。只要索引存在(i in array),就执行回调;空位也会参与判断(即回调不被执行,但该位置不计入结果)。
立即学习“Java免费学习笔记(深入)”;
- 返回数组长度由实际保留项数决定,与原数组无关
-
0、''、null等本身不被过滤,只有回调返回false、0、""等经Boolean()转为false时才剔除 - 适合条件过滤、去重预处理、权限校验等需要子集的场景
reduce:累加器状态机,初始值决定起点逻辑
它的行为完全由是否提供初始值(init)控制:
- 有初始值:第一轮
accumulator = init,currentValue = arr[0] - 无初始值:
▸ 空数组 → 抛TypeError
▸ 单元素 → 直接返回该元素(不调用回调)
▸ ≥2 元素 → 第一轮accumulator = arr[0],currentValue = arr[1] - 回调必须返回值,否则下一轮
accumulator变成undefined - 适合求和、扁平化、分组统计、链式状态累积等聚合类操作
性能上,原始 for 循环最快,因其无函数调用开销;forEach 次之;map/filter 因需构造新数组略慢;reduce 因状态维护和更多边界检查最耗资源。但性能差异在万级数据以下通常可忽略,语义准确性和可维护性才是首要考量。


















