⭐ 推荐:社区规则条款 V1.0

js 数组 map forEach filter 区别

GJ论坛站长
GJ论坛站长 管理员资深会员 👑黑卡会员
发布于 2026-10-19 00:04 ·3 浏览 ·0 回复
内容摘要

map 转换并返回等长新数组,filter 筛选并返回长度可变的新数组,forEach 仅遍历执行副作用且返回 undefined、不能链式调用;三者均全量遍历且不改变原数组本身,应按语义选用,需 break 或 await 时改用 for

**结论:map 用来“转换”,返回一个长度与原数组相同的新数组;filter 用来“筛选”,返回长度可变的新数组;forEach 只用来“遍历执行副作用”,固定返回 undefined,无法链式调用。** 三者都接收 (element, index, array) 三个回调参数,都属于 ES5(2009 年)引入的数组迭代方法,底层都是 O(n) 全量遍历,选择依据应该是语义而不是性能。

map 和 forEach 有什么区别

结论:map 的返回值是新数组,forEach 的返回值永远是 undefined——这是两者唯一不可互换的差别。

const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);   // [2, 4, 6]
const nothing = nums.forEach(n => n * 2); // undefined

因为 forEach 返回 undefined,所以 arr.forEach(...).filter(...) 会直接抛 TypeError: Cannot read properties of undefined。只要你的下一步还想继续链式处理数据,就必须用 map。

另一个高频问题(坑)是:map 的回调必须写 return,用箭头函数加花括号而漏掉 return 时,会得到一个全是 undefined 的等长数组。forEach 则不需要返回值,它的目的就是副作用——发请求、console.log、往外部变量 push。

filter 和 map 有什么区别

结论:map 输出长度恒等于输入长度,filter 输出长度只能小于或等于输入长度。

filter 的回调需要返回一个布尔值(truthy / falsy),返回真值的元素进入结果数组。它不能修改元素值,只能决定元素去留:

const users = [{age: 17}, {age: 20}, {age: 30}];
users.filter(u => u.age >= 18); // [{age:20}, {age:30}],长度 3 → 2

常见错误是在 filter 回调里写赋值而不是比较,例如 filter(u => u.age = 18),赋值表达式返回 18(truthy),结果会原样返回全部元素,并且顺手改坏了原数据。想“筛选 + 变形”就链式写 filter 再 map,顺序建议先 filter 后 map,能少跑一半回调。

三个方法会改变原数组吗

结论:三个方法本身都不改变原数组的长度和引用,但回调内部可以改到原数组里的对象。

map、filter、forEach 都只做遍历,不会 push/splice 原数组。但如果元素是引用类型,回调参数拿到的是同一个对象引用,写 arr.forEach(o => o.done = true) 会真实修改原对象。另外,遍历过程中新增的元素不会被访问到,删除的元素会被跳过;三个方法都会跳过稀疏数组的空位([1, , 3] 只回调 2 次)。

该用哪个:一张决策表

结论:要新数组且一一对应用 map,要新数组且数量会变用 filter,不要返回值用 forEach,要中途 break 或 await 就换 for...of。

  • 需要 break / continue / return 提前退出:forEach 做不到,只能抛异常或改用 for / for...of。
  • 回调里要 await:forEach 不会等待,arr.forEach(async ...) 会在第一个 await 前就结束;应改用 for...of 或 await Promise.all(arr.map(async ...))。
  • 只需要布尔结论:用 some / every,它们遇到确定结果就短路,比 filter 快。
  • map(parseInt) 是经典错误:['1','2','3'].map(parseInt) 得到 [1, NaN, NaN],因为 map 会把索引当作第二个参数传进去,变成 parseInt('2', 1) 这种非法进制。正确写法是 map(s => parseInt(s, 10))。

三者都是全量遍历,V8 下的耗时差异在微秒级以下,不要为了“性能”在 map 和 forEach 之间纠结——按语义选,代码可读性收益远大于那点差异。

总结一句:**要结果数组,看数量是否一一对应来决定 map 还是 filter;不要结果数组,用 forEach;需要控制流,直接用 for...of。**

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2279.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~