在日常的业务开发中,我们通常需要对后端返回的数据解构进行处理,得到我们想要的格式,而其中比较常见的场景便是对数组的操作。最开始用的时候只是看他人写法或者去菜鸟教程大致看一下demo,对于一些方法之间的区别、是否运用得合理没有明确的概念。一些用的较少的方法,还需要去google一下(惭愧.jpg)。还有一些方法(比如reduce)是之前有同学推荐过,但是一直没去用的,这次希望也能彻底搞定。因此本次博客希望对数组相关的方法进行一个比较深入的总结,希望通过这次学习我能真正地了解数组,最好也不要再用一次“gugou”一次了QAQ。
1.some 和 find
当我们需要在数组中寻找一个元素时,我们通常会想到Array.find。它需要一个回调函数,并返回符合条件的第一个元素。然而,当我们仅仅需要知道数组中是否存在符合条件的元素时,Array.some或许是一个更好的办法,因为它返回的是一个布尔值。
语法:Array.find(fn, thisArg)
fn 表示在数组每一项上执行的函数,接受三个参数:
value 当前正在被处理的元素的值
index 当前元素的数组索引
array 数组本身
thisArg 可选,用来当做fn函数内的this对象
说到find,在es6中它有一个兄弟Array.findIndex。它的入参和find基本一致,只不过它返回的是第一个符合条件的项在数组中的位置,如果没有符合条件的则返回-1。
2.find 和 filter
filter的中文意思是过滤,正如其名字所言,它的功能便是通过回调函数过滤数组,并将过滤后的项作为一个新数组返回。
看到上文中我们丢下find使用some的场景,find有些不服气。find曰:看看下面这个场景——我们需要通过一个唯一的ID 为过滤条件去过滤一个数组。如果此时用Array.filter的话,它将会遍历整个数组,当数组项很多时会多次执行回调函数。而明显本场景最终将只有一个符合条件的数据,我们用find在搜寻到第一个符合条件的结果后立即返回。从性能的角度上来说,让我们恭喜find!
3.indexOf 和 includes
Array.indexOf这个方法我们都狠熟悉了,它返回第一个指定元素的下标,如果不存在则返回-1。如果我们不需要知道下标,可以使用直接返回布尔值的 Array.includes。说到返回布尔值,你们有没有想起上面提到的some呢。注意了,注意了,一定要分清楚哦。Array.includes 的第一个入参是一个值, Array.some 的第一个入参是回调函数。includes简单,而some方法可以用来处理较为复杂的数组项哦。
4.reduce来咯
我们什么情况下可以使用reduce呢,有一个比较容易记的方法。当一个场景中我们需要先用Array.filter对数组进行过滤操作,然后对其进行遍历,用map方法返回一个新数组。此时我们可以用Array.reduce方法,一样的味道,更好的配方哦。Array.reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])。
callback 接受四个参数,分别是:accumulator,累加器累加回调的返回值; currentValue,数组中正在处理的元素;currentIndex(可选),数组中正在处理的当前元素的索引;array(可选),调用 reduce() 的数组。initialValue 为可选参数,作为第一次调用 callback 函数时的第一个参数的值。方法的返回值是函数累计处理的结果。
PS:这里通过查阅资料还得知了mdn的语法,可选参数用括号+逗号 [,
表示,而必需的参数只用逗号,
。
光说不练假把式,让我们来进入实战!
emmm我们来模拟一个后端童鞋返回的数据。
[{
id: 1,
name: 'A',
number: 6
}, {
id: 2,
name: 'B',
number: 9
}, {
id: 3,
name: 'C‘,
number: 2
},...]
Round 1
先从简单的开始,我们来统计number的总和吧。
arr.reduce((total, { number }) => {
return total + number;
})
Round 2
加大难度,我们来将数组每项转换为字符串,项之间用空格隔开。
arr.reduce((str, { id, name }) => {
return str + `id:${id},type:${name}+ `;
}, '')
Round 3
boss关,我们来将数组转换成 key value 的对象形式。
arr.reduce((obj, { id, ...value }) => {
obj[id] = {
...value,
}
return obj;
}, {})
最终返回的结果为
{
'1': { name: 'A', number: 6 },
'2': { name: 'B', number: 9 },
'3': { name: 'C', number: 2 }
}
闯关成功,希望我们能学以致用,在今后的工作中很好滴运用这个方法😄
5.foreach 和 map
首先,我们可以明确的是,forEach()方法不会返回执行结果,而是undefined,而map()方法会得到一个新的数组并返回。forEach()允许callback更改原始数组的元素。map()返回新的数组。
项目中有很多地方直接在map方法的回调函数中修改原始数组的值,其实这样做是不建议的。这么做能行得通是因为js中的数组是引用类型,所以可以利用类似指针的特性通过改变另一个变量去修改原始的值。但是!但是!map方法体现的是数据不可变的思想。该思想认为所有的数据都是不能改变的,只能通过生成新的数据来达到修改的目的,因此直接对数组元素或对象属性进行操作的行为都是不可取的。这种思想其实有很多好处,最直接的就是避免了数据的隐式修改。我们来举个栗子。
let arr = [{
a:1,
b:2,
}, {
a:3,
b:4,
}];
//让我们来修改a的值为3
arr = arr.map((item) => { // 返回一个新的数组
return {
...item,
a:3
}
});
emmm可能还有一些数组的方法没有照顾周全,如果以后还遇到一些问题和一些对数组巧妙操作的方法,我们再记录。