JS 数组的几个遍历方法你都会用的吧

photo © screenrant.com

🎼 前言

希望这篇文章对你来说都能是废话。

面试前端候选人的时候,我喜欢问两个方面,一是基础知识,二是代码习惯。我认为,只有基础知识扎实的人才会对代码中的臭味敏感,而代码习惯好的才会有意识地去避免代码发臭。

而数组的几个遍历方法的用法,是我必问的基础知识。

JS 的数组有多少原生用于遍历方法?每个方法的作用什么?你是否知道什么情况下该用那个方法最合适?

我见过很多前端新人,甚至不少顶着「资深」、「专家」头衔的同学,在数组遍历方法的使用上有着各种各样的问题,让读代码的我气不打一处来:

  • 有凡事求告 lodash 的(可能完全不知道原生的 Array 就可以做到)
  • 有拿 map 当 forEach 用的
  • 甚至有拿 filter 当 forEach 的
  • 有认为在 forEach 里 return 会跳出循环的
  • 有不知道 reduce 怎么用的

其中,拿 map 当 forEach 用是我见过最多的问题(我敢判断他纯粹是英语差)。

map 的效率一定是比 forEach 差的,因为它还要创建新数组,往新数组里插数据。但我不拿效率说事,对于目前的电脑性能来说,数据量没有达到一定的程度,这点效率消耗用户是完全感知不到的。我只论语义性,拿 map 当 forEach 使,跟你跟我说给我点外卖,却自己刷了半天抖音一个道理。

适合读者

  • 前端开发
  • 不清楚数组有多少遍历方法的
  • 瞎用数组遍历方法,随心所欲、毫无章法的

编辑历史

日期 版本说明
2023/09/08 V1

🎗️ 完全 / 非完全遍历

数组的遍历方法,是指这个方法接收一个回调函数作为参数,这个回调函数 起码 会接收到当前值、当前位置和数组本身作为参数。

跟 for 循环可以 break 不一样,数组遍历方法是否能够跳出循环,是不能在语法层面控制的。有的方法一定会在全部遍历完成后才结束,有的则有可以中途提前结束循环。

因此,遍历方法可以分为「完全遍历」和「非完全遍历」两种。

方法 完全遍历
forEach ✅
filter ✅
map ✅
some ❌
every ❌
find ❌
findLast ❌
findIndex ❌
findLastIndex ❌
reduce ✅
reduceRight ✅

🎋 遍历方法选择策略

如何选择合适的遍历方法,是体现你基础知识是否扎实,保证不让维护者在这方面唾弃你的代码的关键。

我之前带过几个人做项目,对 CR 中重复指出数组方法问题不厌其烦,于是我画了一个图给他们,让他们以后不会选合适的方法时对照着看:

假设原数组类型为 Array<T>,则根据以下步骤选择方法:

  1. 仅遍历,不需要返回结果
  • 不需要提前结束循环 → forEach
  • 需要提前结束循环 → some
  1. 返回结果类型依然为 Array<T> → filter
  2. 返回结果类型为非 T 数组,看结果长度与原数组是否相同
  1. 返回结果类型为 T | undefined → find / findLast
  2. 返回结果类型为 boolean → some / every
  3. 返回结果类型为 number,是否和元素位置有关
  1. 返回结果类型为其他(字符串、对象等) → reduce / reduceRight

其中,forEach 本身就没有返回值;别的方法,除了 some 可以偶尔忽略返回值之外,若忽略其返回值,则代码一定有问题。

仅遍历,不需要返回结果

不需要提前结束循环

毫无疑问用 forEach。

当然,这里也可以用 for、for..in、for..of 等。还是那句话,在数量级没有达到一定程度的情况下,谈 forEach 的性能没有这些好,是毫无意义的。

需要提前结束循环

用 some,忽略其返回值。

你说用 every 也可以?没错,但代码会难以理解,为了代码的可读性和一致性,请用 some。也就是说,当 every 的返回值被忽略的时候,说明代码有问题。

当然,这里也可以用带 break 的 for、for..in、for..of。

返回结果类型依然为 Array<T>

毫无疑问用 filter。

返回结果类型为非 T 数组

结果长度与原数组相同

一个数组生一个不同类型,相同长度的数组,毫无疑问用 map。

结果长度与原数组不同

一个数组生一个不同类型,且不同长度的数组,用 reduce / reduceRight。

返回结果类型为 T | undefined

其实就是「找到一个元素」或者「找不到」,用 find / findLast。

如果你喜欢 .filter(...)[0],那么恭喜你,基础知识不过关。

返回结果类型为 boolean

用 some / every。

你说 includes?很好,能用的时候用它,但它严格来说不是本文所说的带回调的「遍历」方法。

再一句,includes 比 arr.indexOf(o) >= 0 要好的多。

返回结果类型为 number

跟元素位置有关

找元素的位置,用 findIndex / findLastIndex。

你又说 indexOf / lastIndexOf?又很好,能用就用,但它们又严格来说不是本文所说的带回调的「遍历」方法。

跟元素位置无关

比如,把所有元素对象中的某个数值相加得到一个总数,用 reduce / reduceRight。

返回结果类型为其他

用 reduce / reduceRight。

🧮 来点统计

以下是我的一个项目下的统计数据,非权威数据。

map 真的用的很多,尤其是在有接口数据处理的时候。

🪭 写在最后

虽然,这篇文章对多数人来说都是废话,可我还是希望作为前端开发,可以沉下心来好好夯实基础,优化变成习惯。

如果,你看了这篇文章觉得毫无收获,那么恭喜你。

相关推荐
Jmyd01236 小时前
Web端3D营销展厅技术实现路径:从素材上云到线索回流的数据链路
前端·3d·性能优化·三维数字化
半个落月6 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
砚凝霜6 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
半个落月6 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
u0111026758 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus8 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
派小心.9 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
hhb_6189 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
Java后端的Ai之路9 小时前
08_React组件API
前端·react.js·前端框架
小马不起床9 小时前
零基础玩转 FastAPI_09:前端基础工程构建
前端·状态模式·fastapi