JavaScript数组方法实战:indexOf、find、some与reduce的正确用法

作者:霁月时间:2026-10-22 17:39:18浏览:102

本文深入解析JavaScript中Array对象的常用方法,对比indexOf与includes、filter与find、以及链式filter/map与reduce的性能差异。通过具体代码示例,阐述如何根据实际需求选择返回布尔值或元素的方法,避免不必要的数组遍历,提升代码执行效率与可读性。

JavaScript数组方法实战:indexOf、find、some与reduce的正确用法

前言

近期在审查代码时,我注意到拉取请求中反复出现四起完全相同的JavaScript数组使用错误。基于这些常见误区,本文旨在总结并澄清JavaScript中Array方法的正确使用场景与最佳实践。

Array是JavaScript的内置对象,主要包含以下核心属性:

属性 描述
constructor 返回对创建此对象的数组函数的引用。
length 返回数组中元素的个数
prototype 向对象添加属性和方法。

用 Array.includes 替代 Array.indexOf

用 Array.includes 替代 Array.indexOf

在初学JavaScript时,常见的建议是“若需查找数组中的元素,请使用 Array.indexOf”。这一说法在特定场景下确实成立。

根据MDN文档,Array.indexOf 的功能是“返回给定元素第一次出现的索引”。因此,当后续代码逻辑依赖于获取该元素的索引位置时,使用 Array.indexOf 是合理的选择。

然而,如果我们的目的仅仅是确认数组中是否包含某个特定值,这本质上是一个布尔判断(是或否)。针对此类场景,推荐使用直接返回布尔值的 Array.includes 方法。


'use strict';

const characters = [
 'ironman',
 'black_widow',
 'hulk',
 'captain_america',
 'hulk',
 'thor',
];

console.log(characters.indexOf('hulk'));
// 2
console.log(characters.indexOf('batman'));
// -1

console.log(characters.includes('hulk'));
// true
console.log(characters.includes('batman'));
// false

使用 Array.find 替代 Array.filter

使用 Array.find 替代 Array.filter

Array.filter 是一个高频使用的数组方法,它接收一个回调函数作为参数,遍历数组并返回一个由所有满足条件元素组成的新数组。正如其名,该方法用于筛选出符合条件的子集。

但是,如果回调函数的逻辑预期只返回单个元素(例如通过唯一ID查找特定对象),使用 Array.filter 并不合适。因为 filter 会返回一个仅包含一个元素的新数组,而我们的意图往往是直接获取该元素本身。

从性能角度分析,Array.filter 必须遍历整个数组以找出所有匹配项。如果假设数组中有数百个元素满足回调条件,生成的过滤后数组将占用大量内存,造成不必要的性能开销。

为避免上述问题,建议使用 Array.find。它同样接收回调函数作为参数,但一旦找到第一个满足条件的元素,便立即返回该元素的值并停止遍历。这种方式不仅性能更优,也更清晰地表达了“查找首个匹配项”的代码意图。


'use strict';

const characters = [
 { id: 1, name: 'ironman' },
 { id: 2, name: 'black_widow' },
 { id: 3, name: 'captain_america' },
 { id: 4, name: 'captain_america' },
];

function getCharacter(name) {
 return character => character.name === name;
}

console.log(characters.filter(getCharacter('captain_america')));
// [
// { id: 3, name: 'captain_america' },
// { id: 4, name: 'captain_america' },
// ]

console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }

用 Array.some 替代 Array.find

用 Array.some 替代 Array.find

这一错误我也曾频繁犯下,直到一位同事建议参考MDN文档。其逻辑与前述 indexOf/includes 的对比类似。

在前例中,Array.find 接收回调函数并返回一个具体的元素值。但如果我们仅关心数组中是否存在某个值,Array.find 并非最佳方案,因为它返回的是元素而非布尔判断结果。

针对此类“存在性检查”场景,推荐使用 Array.some。它返回所需的布尔值(true或false)。从语义上看,Array.some 明确表示我们只关心元素是否存在,而不需要获取元素本身。


'use strict';

const characters = [
 { id: 1, name: 'ironman', env: 'marvel' },
 { id: 2, name: 'black_widow', env: 'marvel' },
 { id: 3, name: 'wonder_woman', env: 'dc_comics' },
];

function hasCharacterFrom(env) {
 return character => character.env === env;
}

console.log(characters.find(hasCharacterFrom('marvel')));
// { id: 1, name: 'ironman', env: 'marvel' }

console.log(characters.some(hasCharacterFrom('marvel')));
// true

使用 Array.reduce 替代链式 Array.filter 和 Array.map

使用 Array.reduce 替代链式 Array.filter 和 Array.map

不可否认,Array.reduce 的学习曲线较陡,理解难度较大。但如果我们习惯性地链式调用 Array.filter 和 Array.map,可能会感到代码冗余且效率低下。

具体而言,这种链式调用意味着对数组进行了两次遍历:第一次通过 filter 生成一个较短的中间数组,第二次基于该中间数组通过 map 生成包含新值的目标数组。这不仅使用了两个方法,还产生了由 filter 创建的无用中间数组,造成性能损耗。

为了消除这种性能浪费,建议直接使用 Array.reduce。虽然结果相同,但代码更为简洁高效。我们可以利用 reduce 在遍历过程中直接进行过滤,并将符合条件的元素添加到累加器中。累加器可以是数字、对象、字符串或数组。

在本文示例中,鉴于此前使用了 map 的逻辑,我们改用 reduce 将满足条件的数组元素直接加入累加器。如下例所示,根据 env 值的具体情况,我们将元素添加到累加器中,否则保持累加器不变。


'use strict';

const characters = [
 { name: 'ironman', env: 'marvel' },
 { name: 'black_widow', env: 'marvel' },
 { name: 'wonder_woman', env: 'dc_comics' },
];

console.log(
 characters
 .filter(character => character.env === 'marvel')
 .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
);
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]

console.log(
 characters
 .reduce((acc, character) => {
  return character.env === 'marvel'
  ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
  : acc;
 }, [])
)
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]

英文原文:

https://medium.freecodecamp.org/heres-how-you-can-make-better-use-of-javascript-arrays-3efd6395af3c

总结

以上内容涵盖了本文的核心观点,希望能为读者在JavaScript数组方法的学习与工作中提供有价值的参考。如有任何疑问,欢迎留言交流,感谢支持。

作者最新文章