很多人始终不明白,ES6 数组的遍历方法最重要的不在代码本身,而是语义化!map、reduce、filter、some、every、find ...

前言

不知不觉,ES6 的数组新语法已经出了好多年了,大家都应该理解一句话: ES6 数组方法带来的最大优势是语义化

很多人在使用 ES6 数组语法时,将它当作了便捷操作。

甚至更多千奇百怪的用法,我希望大家在看完该文章后,去检查一下自己的项目中,这些语法是否可以一眼让大家看出这些方法是做什么用的。

反面操作

这里简单列举一些反面操作:

  • map 作为循环使用,通过 map 计算总数
JS 复制代码
const arr = [{..., count: 1}, {..., count: 5}]

const total = 0;
arr.map(v => {
    total += v.count
})
  • map 作为循环使用,改变数组中的对象的属性
JS 复制代码
// 操作1
let arr = [{..., id: '1'}, {..., id '2'}]
arr = arr.map(v => ({...v, id: Number(id)}))

// 操作2
let arr = [{..., id: '1'}, {..., id '2'}]
arr.map(v => {
    v.id = Number(v.id)
})

其中尤其是改变对象属性中的操作1,是误用最多的用法。

讲解

我一般不做基本语法讲解,因为罗列式的讲解让你左脑进右脑出,不带给大家任何价值。面向实际的使用才能让大家影响深刻。

接下来,我将假设自己是一个快递站的老板,我作为一个快递站的老板,应该如何通过这些语法来处理我的快递。

为了让代码更清晰,我将以 ed 来作为快递的简称(express delivery)

map

语义 :将一些东西转换为另一些东西。

正面示例:

我需要将所有的 快递单号 + 派送时间 整理出来,来决定我的送货顺序。

JS 复制代码
const edArr = [{..., id: '666666666', date: '2024-02-23'}, {..., id: '666666688', date: '2024-02-22'}, ...]

const data = edArr.map(v => ({id: v.id, date: v.date}))

反面示例:

我希望给所有快递贴一个广告。

JS 复制代码
let edArr = [{..., id: '666666666', date: '2024-02-23'}, {..., id: '666666688', date: '2024-02-22'}, ...]

edArr = edArr.map(v => ({...v, ad: '要问快递哪家强,就来掘金找sincenir!'}))

虽然反面案例也能实现,并且也没有代码量的提升,但是我强烈不建议这么干。这会大大降低你代码的可阅读性。

foreach

语义:我希望循环做某些事。

显然,相较于 map ,上面的反面案例应该交由 foreach 操作,而正面案例则是 foreach 的反面案例。这两者大家常常是反着用的。

正面示例:

我希望给所有快递贴一个广告。

JS 复制代码
let edArr = [{..., id: '666666666', date: '2024-02-23'}, {..., id: '666666688', date: '2024-02-22'}, ...]
edArr.foreach(v => { v.ad = '要问快递哪家强,就来掘金找sincenir!' })

反面示例:

我需要将所有的 快递单号 + 派送时间 整理出来,来决定我的送货顺序。

JS 复制代码
const edArr = [{..., id: '666666666', date: '2024-02-23'}, {..., id: '666666688', date: '2024-02-22'}, ...]

const data = []
edArr.foreach(v => {
    data.push({id: v.id, date: v.date})
})

filter

语义:我希望筛选出来一些东西。

正面示例:

我希望找到所有用户拒收的快递,发回给快递公司。

JS 复制代码
const edArr = [{..., reject: false}, {..., reject: true}, ...]
const rejectEdArr = edArr.filter(v => v.reject === true)

反面示例:

我希望找到单号为 8888 的快递。

JS 复制代码
const edArr = [{..., id: '6666'}, {..., id: '8888'}, ...]
const nArr = edArr.filter(v => v.id === '8888')

显而易见的是,快递单号是唯一的,用 filter 在这里是不合适的。

因为它最多筛选出一个符合条件的快递,且这个一是已知的。

find

语义:找一个符合条件的给我。

正面示例:

快递员:我车装差不多了,再给我一个 270号楼 的快递,我一块儿送过去。

JS 复制代码
const edArr = [{..., address: '271'}, {..., address: '270'}, ...]
const oneEd = edArr.find(v => v.address === '270')

反面示例:

顾客:今天有没有我的快递?

JS 复制代码
const edArr = [{..., user: 'zhangsan'}, {..., user: 'sincenir'}, ...]
const ed = edArr.find(v => v.user === 'sincenir')

if (ed) {
    // 有
} else {
    // 没有
}

findIndex

语义:找符合条件的是第几个。

正面示例:

快递员:我今天还需要送多少快递?

JS 复制代码
const edArr = [{..., date: '2024-02-23'}, {..., date: '2024-02-24'}, ...]
const count = edArr.findIndex(v => v.date !== '2024-02-23') + 1

反面示例:

顾客:今天有没有我的快递?

JS 复制代码
const edArr = [{..., user: 'zhangsan'}, {..., user: 'sincenir'}, ...]
const haveSincenir = edArr.find(v => v.user === 'sincenir') > -1

这里需要提醒大家,findIndex 是滥用极其严重的函数,包括有没有很多人都喜欢用 findIndex 去做,这些都是不对的。

当你不知道你是否要使用 findIndex 时,据我观察,大多数时候都应该使用别的语法。

some

语义:这里有没有符合条件的。

正面示例:

顾客:这里有没有我的快递?

JS 复制代码
const edArr = [{..., user: 'zhangsan'}, {..., user: 'sincenir'}, ...]
const haveSincenir = edArr.some(v => v.user === 'sincenir')

every

语义:这里是否全符合条件。

正面示例:

快递员:今天还有没有需要送的快递啦?

JS 复制代码
const edArr = [{..., date: '2024-02-23'}, {..., date: '2024-02-24'}, ...]
const haveToday = edArr.every(v => v.date !== '2024-02-23')

reduce

语义:基于这些帮我算一个东西。

正面示例:

咱们今天收的快递总共多少钱啊?我算算账对不对。

JS 复制代码
const edArr = [{..., amount: '13'}, {..., amount: '20'}, ...]
const totalAmount = edArr.reduce((r, v) => (r + v.amount), 0)

最后

语义化最重要的点在于,我们看到代码的第一眼,不需要看细节就能明白我们究竟准备做什么。

而不是为了便捷去使用这些方法,否则你的代码依旧是面条形状的面向过程编程。

最后我们总结下所有语法的语义:

  • map: 将一些东西转换为另一些东西
  • foreach: 我希望循环做某些事
  • filter: 我希望筛选出来一些东西
  • find: 找一个符合条件的给我
  • findIndex: 找符合条件的是第几个
  • some: 这里有没有符合条件的
  • every: 这里是否全符合条件
  • reduce: 基于这些帮我算一个东西
相关推荐
Highcharts.js2 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC2 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
浮生望3 小时前
React useState 深度解析:异步更新、闭包陷阱与惰性初始化的底层逻辑
react.js
Patrick_Wilson6 小时前
从 React 到 Flutter:写给前端的一张跨端知识地图
前端·flutter·react.js
kyriewen7 小时前
我review了一份Vibe Coding写的前端代码——能跑,但5个地方迟早要命
前端·javascript·ai编程
腻害兔8 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:IM 即时通讯模块,一个被低估的「全功能聊天系统」
java·前端·vue.js·产品经理·ai编程
Hilaku10 小时前
为什么在 2026 年,MPA(多页面应用)正在悄悄复辟?
前端·javascript·程序员
悟空瞎说10 小时前
iOS 高效绘图
javascript
触底反弹10 小时前
🔥 从 MySQL 到 Milvus:用 AI 日记本项目搞懂向量数据库和 RAG
javascript·人工智能·面试
妙码生花10 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(三十九):前端上传组件实现
javascript·vue.js·ai编程