5月28日 03:36
some、every、find、filter、map、forEach 有什么区别?
这 6 个方法是 JavaScript 数组最常用的迭代方法,面试几乎必考。核心区别在于返回值类型和是否短路,按返回值分三类记忆最清晰。
一、遍历类(无返回值)
forEach
纯遍历,对每个元素执行回调,返回值永远是 undefined。
- 不能中断:
return只跳过当前回调,break语法不支持,想中途退出只能用try/catch抛异常(不推荐) - 不支持异步:回调里写
async/await不会等待 Promise,因为forEach不关心返回值
javascriptconst list = [1, 2, 3]; list.forEach(item => console.log(item)); // 1, 2, 3 // return 只跳过当次,不会中断循环
二、返回新数组
map
每个元素经回调映射后返回等长新数组,不改变原数组。
javascriptconst nums = [1, 2, 3]; const doubled = nums.map(n => n * 2); // [2, 4, 6]
filter
返回满足条件的元素组成的新数组,长度可能小于原数组,不改变原数组。
javascriptconst nums = [1, 2, 3, 4, 5]; const big = nums.filter(n => n > 3); // [4, 5]
三、返回布尔值或单个元素
find
返回第一个满足条件的元素,找到即停止遍历(短路)。找不到返回 undefined。
javascriptconst users = [{id: 1, name: 'A'}, {id: 2, name: 'B'}]; users.find(u => u.id === 2); // {id: 2, name: 'B'}
some
有任意一个满足条件就返回 true,找到即短路。全不满足返回 false。空数组返回 false。
javascript[1, 2, 3].some(n => n > 2); // true [1, 2, 3].some(n => n > 5); // false [].some(n => n > 0); // false
every
所有元素都满足条件才返回 true,遇到不满足即短路。空数组返回 true(空真逻辑 vacuous truth)。
javascript[1, 2, 3].every(n => n > 0); // true [1, 2, 3].every(n => n > 1); // false [].every(n => n > 0); // true(空真)
四、对比速查表
| 方法 | 返回值 | 是否短路 | 空数组返回 | 链式调用 | 修改原数组 |
|---|---|---|---|---|---|
| forEach | undefined | 否 | undefined | 否 | 否 |
| map | 新数组 | 否 | [] | 是 | 否 |
| filter | 新数组 | 否 | [] | 是 | 否 |
| find | 单个元素/undefined | 是 | undefined | 否 | 否 |
| some | boolean | 是 | false | 否 | 否 |
| every | boolean | 是 | true | 否 | 否 |
五、高频追问
map 和 forEach 怎么选?
需要返回新数组用 map,纯副作用(如 console.log、DOM 操作)用 forEach。关键区别:map 可链式调用,forEach 返回 undefined 不可链式。
some 和 includes 有什么区别?
includes(val)判断数组是否包含某个具体值,用严格相等(===)比较some(fn)判断是否有元素满足自定义条件includes只能判断值存在性,some可以写任意判断逻辑
javascript[1, 2, 3].includes(2); // true [1, 2, 3].some(n => n > 2); // true [{a: 1}].includes({a: 1}); // false(引用不同) [{a: 1}].some(o => o.a === 1); // true
这些方法支持异步回调吗?
都不原生支持。forEach 里写 async/await 不会等待 Promise resolve。需要异步迭代用 for...of + await 或 Promise.all + map。
javascript// 错误:forEach 不会等待 async ids.forEach(async id => { const data = await fetch(id); // 并发执行,不会依次等待 }); // 正确方式1:for...of for (const id of ids) { const data = await fetch(id); } // 正确方式2:Promise.all + map(并行) const results = await Promise.all(ids.map(id => fetch(id)));
find 和 filter 怎么选?
只需第一个匹配用 find(性能更好,短路),需要所有匹配用 filter。
reduce 为什么没列进来?
reduce 是这 6 个方法的基础——map、filter、some、every、find 都可以用 reduce 实现。面试中常追问 reduce 的用法,但 reduce 更偏向"累加器"模式,功能更强大也更复杂,属于另一个考点的范畴。