5月28日 03:36

some、every、find、filter、map、forEach 有什么区别?

这 6 个方法是 JavaScript 数组最常用的迭代方法,面试几乎必考。核心区别在于返回值类型是否短路,按返回值分三类记忆最清晰。

一、遍历类(无返回值)

forEach

纯遍历,对每个元素执行回调,返回值永远是 undefined

  • 不能中断return 只跳过当前回调,break 语法不支持,想中途退出只能用 try/catch 抛异常(不推荐)
  • 不支持异步:回调里写 async/await 不会等待 Promise,因为 forEach 不关心返回值
javascript
const list = [1, 2, 3]; list.forEach(item => console.log(item)); // 1, 2, 3 // return 只跳过当次,不会中断循环

二、返回新数组

map

每个元素经回调映射后返回等长新数组,不改变原数组。

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

filter

返回满足条件的元素组成的新数组,长度可能小于原数组,不改变原数组。

javascript
const nums = [1, 2, 3, 4, 5]; const big = nums.filter(n => n > 3); // [4, 5]

三、返回布尔值或单个元素

find

返回第一个满足条件的元素,找到即停止遍历(短路)。找不到返回 undefined

javascript
const 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(空真)

四、对比速查表

方法返回值是否短路空数组返回链式调用修改原数组
forEachundefinedundefined
map新数组[]
filter新数组[]
find单个元素/undefinedundefined
somebooleanfalse
everybooleantrue

五、高频追问

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 + awaitPromise.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 个方法的基础——mapfiltersomeeveryfind 都可以用 reduce 实现。面试中常追问 reduce 的用法,但 reduce 更偏向"累加器"模式,功能更强大也更复杂,属于另一个考点的范畴。

标签:前端ES6