很多人始终不明白,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: 基于这些帮我算一个东西
相关推荐
Mr.app43 分钟前
vue mixin混入与hook
vue.js
一个专注写代码的程序媛1 小时前
vue组件间通信
前端·javascript·vue.js
一笑code1 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员2 小时前
layui时间范围
前端·javascript·layui
心宽体胖连壮实2 小时前
记录一次 MarchingSquaresJS 使用经历
vue.js
烛阴2 小时前
面试必考!一招教你区分JavaScript静态函数和普通函数,快收藏!
前端·javascript
JiangJiang2 小时前
🚀 React 弹窗还能这样写?手撸一个高质量 Modal 玩起来!
前端·javascript·react.js
吃炸鸡的前端2 小时前
el-transfer穿梭框数据量过大的解决方案
前端·javascript
Monly213 小时前
vue报错:Loading chunk * failed,vue-router懒加载出错问题。
前端·javascript·vue.js
t2007183 小时前
4.27 react第一天
前端·react.js·前端框架