最近做的项目中涉及前端做数据的聚合和处理,用到了很多数组的方法,所以依据功能进行分类总结防止混淆
文章目录
1. 遍历类(只有直接对item操作才会改变,返回值需要特别注意)
forEach
对每一项操作,无返回值
map
return + 操作后的新item
对数组中每项操作,有返回值得到一个新数组,原数组多少项就得到多少项
filter
return + 过滤条件
返回满足条件的数组。和原数组项数不一致
find
return + 满足条件
返回满足条件的第一项(注意返回的是项不是数组,而且是第一项)
some
return + 条件
如果数组中满足这一条件的返回true, 没有则返回false
every
return + 条件
如果数组中每个都满足这个条件则返回true, 不是则返回false
for遍历
【遍历数组】
for(let item of a)
{
}
【遍历对象】
for(let item in a)
{
}
2. 增加删除类(改变原数组,返回值需要特别注意)
push&&pop
push是从后面加一项,返回值是增加后的数组长度
pop是从后面删除一项,返回值是删除的那一项
shift&&unshift
shift是从前面删除一项,返回值是删除的那一项
unshift从前面加入一项,返回值是增加后的数组长度
splice
a.splice(n,m,l,…)
从第n项(包括n)删除m项,把l,…插入到n前面,返回值是删除的数组,原有数组改变。没有第三项的时候表示只删除。没有2,3项的时候表示从第n项删除到最后。
3. 截取和拼接(原有数组不改变,返回值为预想结果)
slice
slice(n, m)
从第n项(包括n)开始截取到m项(不包括m),没有第二项表示到末尾。返回一个截取的新数组,不改变原数组,支持负数索引
concat
a.concat(b,c)
传参是想要拼接的数组/值,可以是多项传参,返回值是拼接后的新数组
4. 顺序相关(改变原数组,返回值为预想结果)
reverse
a.reverse()倒过来,改变原数组,返回值是倒序后的数组
【注意】
如果想得到a的倒序而不改变a,以下是错误的
let a = [1,2,3,4]
let b = a
b.reverse() //返回值是[4,3,2,1]
console.log(a) //打印出来是[4,3,2,1] a被改变了
这样仍然改变了a,因为是按址赋值,a,b共用一个地址,数组是引用类型
【解决】
let b = a.slice()
let b = a.concat()
sort
项目中sort都要有传参,改变原数组,返回值是排序后的数组
let a = [1,2,3,4]
a.sort((a,b) => {return a - b}) //正序
a.sort((a,b) => {return b - a}) //倒序
如果sort里不跟传参会出现问题,根据第一位排序
sort对象数组
在项目中有的是给一个对象数组,要根据该对象数组里的某个属性值排序,写法如下
function compareUp (prop) { //基于对象中的prop属性升序排列
return function (a, b) {
let value1 = a[prop]
let value2 = b[prop]
return value1 - value2
}
}
//用的时候
a.sort(compareUp('month')) //根据month字段排序
降序的话回调函数里改为value2 - value1
5.字符串相关操作(不改变原数组,返回值为预想结果)
toString
a.toString()
把数组转化为数组中的每一项用逗号分隔的字符串,原有数组不改变,返回值为字符串
join
a.join(’+’)
和toString类似,也是把数组转换为字符串,但我们可以是设置为字符串之后,每一项之间的连接符,返回值为字符串
indexOf/lastIndexOf
检测当前值在数组中第一次或者最后一次出现位置的索引,没有则返回-1
6. 数组去重
项目中经常用到数组去重,利用对象健值即可,es6方便一些
var ary=[1,1,2,3,4,5,5,6,7,3];
var newAry=Array.from(new Set(ary));//把其他转为数组
console.log(newAry);
也可以一步一步来,学习一下,如下,好的方法主要是利用了对象的健不能重复
【解决方案一】:
- 依次拿出数组中的每一项(排除最后一项,因为最后一项没有要比较的内容)
- 和当前拿出项后面每一项比较
- 如果有重复的,我们把找到的这个重复项在原有数组中删除掉
var ary=[1,2,2,3,4,5,6,6,7];
for(var i=0;i<ary.length-1;i++)
{
for(var j=i+1;j<ary.length;j++)
{
ary[i]===ary[j]?ary.splice(j,1):null;
}
}
console.log(ary);
//这样做会发生数组塌陷,删除后后面向前进一位,原有数组发生改变,索引改变,此时j继续累加,下一次拿出来的结果就会跳过一位
var ary=[1,2,2,2,3,4,5,6,6,7]
==>[1, 2, 2, 3, 4, 5, 6, 7]
//所以改为
for(var i=0;i<ary.length-1;i++)
{
for(var j=i+1;j<ary.length;j++)
{
if(ary[i]===ary[j])
{
ary.splice(j,1);
j--;//先减后加
}
}
}
【解决方案二】:
浪费性能
不推荐使用双for循环
基于对象属性名不能重复
var ary=[1,2,3,2,2,3,4,3,4,5]
- 创建几个空对象
- 依次遍历数组中的每一项,把每一项存储值当作对象的属性名和属性值存储起来
第一次循环 1 {1:1}
第二次循环 2{1:1,2:2}
第三次循环 3{1:1,2:2,3:3}
第四次循环 2 我们在存储之前做一个判断,判断当前对象中是否已经存在属性名了,如果存在,说明之前有这一项存储的操作,进一步说明之前数组中出现过这个数值了(也就是重重复了,此时我们把当前项从数组中移除即可)
如何判断对象中是否这个属性,如果没有这个属性获取的值是undefined
var ary=[1,2,3,2,2,3,4,3,4,5];
var obj={};
for(var i=0;i<ary.length;i++){
var item=ary[i];
//存储之前要做判断:如果对象中已经存在这个属性,说明当前item出现过,也就是当前项重复了,我们把当前删掉
if(typeof obj[item]!=='undefined'){
// ary.splice(i,1);
// i--;//防止数组塌陷
// 这种删除方式不好,改索引耗性能
// 1.我们把数组最后一项结果获取到,替换当前项内容
// 2.再把数组最后一项删除
ary[i]=ary[ary.length-1];
ary.length--;
i--;//把新值放在这一项,新值还没比较,所以不能+1开始下一项
continue;//继续下一个循环
}
obj[item]=item;
}
console.log(ary);
//注意typeof都是小写
7. 字符串方法
项目中也需要对字符串进行处理,常用方法有
【indexOf/lastIndexOf】和数组一样
【str.toUpperCase/toLowerCase】改变大小写
【replace】替换字符串中原有字符
【split】和join对象,把字符串转化为数组str.split(’,’)
字符串截取
【slice】str.slice(n,m)从索引n开始找到索引m处(不包含m),把找到的字符当新字符串返回,支持负数索引
【substring】和slice语法一模一样,唯一区别在于:substring不支持负数索引
【substr】str.substr(n,m),从索引n开始截取m个字符, 支持负数索引,第二个参数不传,截取到末尾,支持第一个索引为负数索引