一份比较全面的JS数组对象常用方法整理
本文是针对JS数组的常用方法整理,由于js数组的方法大多可以用for循环手动实现因此对提升项目性能可能没有太大帮助,但是熟练使用数组方法可以提高工作效率以及代码的可读性,拥抱函数式编程;
数组对象的join方法
join方法是将数组对象中的,每个对象转换成字符串,并用传入参数字符串进行拼接,并返回一个字符串
let Arr = [1,2,3,4]
console.log(Arr.join(',')) //1,2,3,4
console.log(Arr.join('-')) //1-2-3-4
let Arr2 = [1,2,[3,4],[5,6]]
console.log(Arr2.join(',')) //1,2,3,4,5,6
//若数组中有对象,则会对对象先使用tostring方法,所以对象将会被转换成[object Object],一般不会这么做也不多做说明
let Arr3 =[1,2,{name:'name1',value:1}]//1,2,[object Object]
console.log(Arr3.join(','))
数组对象的push方法
该方法相信大家都很熟悉,是向数组末尾追加元素,改变原数组,但是其实这个方法是有一个返参的(返回改变后的数组长度),大家可能没有注意
let arr = [1,2,3]
console.log(`push返回参数:${arr.push(4)} 追加后的数组对象:${arr} `)//打印结果 push返回参数:4 追加后的数组对象:1,2,3,4
// 注意到打印出的arr.push(4)的反参4没有,没错就是返回拼接后的数组的长度(length属性)
数组对象的pop方法
pop方法将删除 数组的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不改变数组,并返回 undefined 值。
//pop
let arr = [1,2,3]
console.log(arr.pop()) //3 返回的是删除的元素
console.log(arr) //[1, 2] 删除最后一位元素的数组
let arr2 = [1]
console.log(arr2.pop()) //1
console.log(arr2) //[]
let arr3 = []
console.log(arr3.pop()) //undefined
console.log(arr3) //[]
数组对象的splice方法
splice方法从数组中添加/删除项目,然后返回被删除的项目 主要语法为
arrayObject.splice(index,howmany,item1,.....,itemX)
- index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
- howmany:必需。要删除的项目数量。如果设置为 0,则不会删除项目。
- item1, ..., itemX:可选。向数组添加的新项目。
//splice
let arr =[1,2,3,4]
// arr.splice(1,2) //从数组indexOf为1的位置删除两个元素并返回一个数组
console.log(arr.splice(1,2))// [2, 3]
console.log(arr) //[1,4]
let arr2=[1,2,3,4]
arr2.splice(1,2,666,777,888) //从arr2indexOf为1的位置删除两个元素并插入666,777,888三个元素
console.log(arr2) //[1, 666, 777, 888, 4]
let arr3 = [1,2,3,4]
arr3.splice(-1,1,7777)//从arr3末尾删除1个元素并在删除元素位置插入7777
console.log(arr3) //[1, 2, 3, 7777]
let arr4 = [1,2,3,4]
arr4.splice(-1,0,6666)//从arr4末尾删除0个元素并在删除元素位置插入7777
console.log(arr4) //[1, 2, 3, 6666, 4]
let arr5 = [1,2,3,4]
arr5.splice(-2,3,9999)
console.log(arr5)//[1, 2, 9999]
数组对象的indexOf方法
返回输入参数在数组中的位置(第一次出现)
//indexOf
let arr =['a','b','c','d']
console.log(arr.indexOf('c')) //2
let arr2 = ['a','b','b','b']
console.log(arr2.indexOf('b')) //1
数组对象的lastIndexOf方法
返回输入参数在数组中的位置(最后一次出现) 用法就不多做阐述了和indexOf一样
数组对象的reverse方法
颠倒数组中元素的位置,会改变原数组,并返回颠倒后的原数组;
//reverse
let arr = [1,2,3,4]
arr.reverse()
console.log(arr) //[4, 3, 2, 1]
数组对象的slice方法
从已有的数组中返回选定的元素
用法:arrayObject.slice(start,end)
- start:必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
- 可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
//slice
let arr = [1,2,3,4]
console.log(arr.slice(0,2))//[1, 2] //返回arr中第1个元素开始截取两个长度的数组长度
console.log(arr)//[1, 2, 3, 4]//该方法与splice方法不同,只是返回其中一截的数组长度并拼接成数组返回,并不会改变原数组
数组对象的every方法
检索数组对象中每个元素是否都符合要求
let arr = [10,11,12,13]
console.log(arr.every(i=>i>10))//判断arr中所有元素是否大于10//false
console.log(arr.every(i=>i>9)) //判断arr中所有元素是否大于9//true
数组对象的some方法
检索数组对象中是否有符合规则的元素
let arr = [10,11,12,13]
console.log(arr.some(i=>i<9)) //判断arr中是否有元素小于9 //false
console.log(arr.some(i=>i<11)) //判断arr中是否有元素小于11 //true
数组对象的reduce方法
累加器方法,和forEach方法有点类似对数组中对象进行遍历计算并返回最终结果
//reduce
let arr = [1,2,3,4,5,6,7,8,9,10]
console.log( '结果:'+
arr.reduce((x,y)=>{
console.log(`x=>${x}`)
console.log(`y=>${y}`)
return x+y
})
) //55
从输出结果来看你们可以发现第一次运行回调函数的时候x为1,y为2,而第二次x=3,y=3,第三次输出为x=6,y=4,由此可以看出第一次x等于数组的第一个元素值,第二个元素为数组的第二个元素值,而往后,x为回调函数返回的值,y为arr[次数]的值
数组对象的reduceRight方法
//reduceRight
let arr = [1,2,3,4,5,6,7,8,9,10]
console.log( '结果:'+
arr.reduceRight((x,y)=>{
console.log(`x=>${x}`)
console.log(`y=>${y}`)
return x+y
})
) //55
从输出结果来看可以看出,reduceRight方法与reduce方法一样,之后过是从末尾计算追加
数组对象的forEach方法
方法用于调用数组的每个元素,并将元素传递给回调函数(该方法不会改变原数组,但是可以依靠回调函数做到)
let arr = ['aaa','ccc','ddd','eee','bbb']
arr.forEach((currentValue,index,arr)=>{
console.log(`index:${index},value:${currentValue}`)
console.log(arr)
})
/* 此为输出结果
index:0,value:aaa
['aaa','ccc','ddd','eee','bbb']...
forEach方法对数组中的元素进行遍历,进行操作回调函数中的currentValue为遍历的当前元素值,index为当前元素索引,arr是当前元素返回的数组
forEach 方法用于调用数组的每个元素,并将元素传递给回调函数。
如果对数组中的每个元素都要进行操作或者判断则可以使用此方法,如果遍历需要回返则不建议使用
*/
过多的我就不说了,这个平时用的比较多大家基本上都知道用法
数组对象的map方法
对数组进行遍历循环并返回一个新数组;
let arr = ['aaa','ccc','ddd','eee','bbb']
console.log(arr.map((currentValue,index,arr)=>{
return currentValue+index
}))
/* 此为输出结果
[aaa1,ccc2,ddd3,eee4,bbb5]
map方法和forEach方法很像回调方法的都是必传当前遍历元素的值与选填的当前元素索引选填的当前元素所在数组唯一不同的是forEach方法没有返回值但是map方法却会返回一个新数组这用于要对数组中加入一些新子元素非常方便(操作数组)
*/
数组对象的filter方法
过滤器方法,过滤出数组对象中符合自定义规则的元素并组合成一个新数组返回
//filter
let arr = [111,222,333,444,555,666]
console.log(
arr.filter((currentValue,index,arr)=>{
return currentValue>333
})
) //输出结果 [444,555,666]
/**
* filter方法的入参用法用forEach map一样都是currentValue必填,index,arr选填
* filter将会返回一个过滤掉不符合自定义规则的数组的新数组
* */
数组对象的sort方法
多用于数组的排序可传入一个回调函数来定义排序方式,一般在比较Number元素大小时可用,如果数组中元素都是Number类型而又没有传入回调函数则返回原数组,说白了不传回调函数比较大小只对String类型有效,所以又想不传入回调函数又想排序纯Number数组就要先把所有数组元素转换成String类型进行排序,废话不多说直接上代码
let arr = [333,11,666,2,8,123,0]
let arr2 = ['zzz','eee','sss','aaa','ddd']
console.log(arr2.sort()) // ["aaa", "ddd", "eee", "sss", "zzz"]
console.log(arr.sort()) //[0, 11, 123, 2, 333, 666, 8]
//由此可见不传回调函数对纯Number类型的数组是不生效的,可见sort方法的排序方式是通过编码来对数组元素进行排序的
//纯Number类型数组从小到大排序
console.log(arr.sort((a,f)=>{
return a-f
}))//[0, 2, 8, 11, 123, 333, 666]
//纯Number类型数组从大到小排序
console.log(arr.sort((a,f)=>{
return -(a-f)
}))//[666, 333, 123, 11, 8, 2, 0]
数组对象的concat方法
这方法现在不怎么用了吧还是讲一讲,该方法用于拼接数组,可传入多个参数(至少传入一个)返回一个新数组,如果传入的是一个数组则会拼接入数组中的元素而不是数组
let arr = [1,2,3,4,5]
console.log(arr.concat(6,7,8,[9,10],[11],[12,13]))//[1,2,3,4,5,6,7,8,9,10,11,12,13]
数组对象的shift方法
这个不太好用我就简单说明,毕竟一家人最重要的是整整齐齐 如果数组是空的,那么 shift() 方法将不进行任何操作,返回 undefined 值
//shift
let arr = [1,2,3,4,5]
console.log(arr.shift()) //1
console.log(arr) //[2,3,4,5]
//注意啦,这个方法会改变原数组长度的,一般场合都用不到
数组对象的unshift方法
unshift() 方法将把它的参数插入 arrayObject 的头部,并将已经存在的元素顺次地移到较高的下标处,以便留出空间。该方法的第一个参数将成为数组的新元素 0,如果还有第二个参数,它将成为新的元素 1,以此类推。(这段我直接抄的因为不知道如何表达)
//unshift
let arr = [1,2,3,4,5]
console.log(arr.unshift(6)) //6
console.log(arr.unshift([7,8,9]))//7
console.log(arr) //[[7,8,9],6,1,2,3,4,5]
//unshift方法返回的是新数组长度,而shift方法是返回第一个被删除的元素,这两个方法都会改变数组长度,而传入的参数如果是个数组将不会和concat方法一样将传入数组元素打散
扩展运算符
在ES5中我们要将两个打散数组合并会用到数组对象的concat方法
let arr = [1,2,3,4,5,6,7,8,9,0]
console.log(arr.concat([1],[1,2,3,4],'aaaa',['bbbb','dddd'])) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 1, 2, 3, 4, "aaaa", "bbbb", "dddd"]
concat方法最终会返回一个拼接完的数组,也就是我们所需的结果 如果用扩展运算符又是如何操作呢?
let arr = [1,2,3,4,5,6,7,8,9,0]
console.log(...arr) //1 2 3 4 5 6 7 8 9 0
let arr2 = [...arr,...[1],...[1,2,3,4],'aaaa',...['bbbb','dddd']]
console.log(arr2) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 1, 2, 3, 4, "aaaa", "bbbb", "dddd"]
不仅可以打散数组,扩展运算符也可以打散字符串
console.log([...'hello world']) //['h','e','l','l','o',' ','w','o','r','l','d']
当然也能运用于数组的解构赋值
let [a,...b] = [1,2,3,4,5,6]
console.log(a)//1
console.log(b)//[2,3,4,5,6]
//但是必须要知道的一点是在进行数组的解构赋值时只能作用于数组的最后一位,不然会报错!
let[...c,d] = [22,33,44,55] //Uncaught SyntaxError: Rest element must be last element
当然也可以和Aray.from()一样,将一个类数组转换成数组
let set = new Set([1,2,3,4,5,6,7,8])
console.log([...set]) //[1, 2, 3, 4, 5, 6, 7, 8]
运行后可知,...可将Array对象打散,在数组中打散则会返回一个新的数组,对于使用长逻辑时,有时候concat可能会使代码看起来并不是很易懂,用这个会好很多。但是扩展运算符并不是主要用来打散重组数组的。把它用在方法传参中,会用起来很简洁灵活
let arr = [1,2,3,4,5,6,7,8,9,0]
function add(...arr){
let aaa = arguments[0].reduce((i,j)=>{
return i+j
})
console.log(aaa)//45
}
add(arr)
当然也可以这样子做
function testFoo(a,b,c,d){
return a+b+c+d
}
let arr = [1,2,3,4]
testFoo(...arr)
类方法from
将类数组对象和迭代器对象转换成数组最常用的应该就是数组去重操作了
let arr = [1,2,3,3,3,3,444,4,4,4,5,5,'a','a','b','f']
let set = new Set(arr) //set数据类型中不会存在相同的元素,因此把数组转换成set会将数组中重复的部分去除
let newArr = Array.from(set) //将set数据类型转换成数组
console.log(newArr) //[1, 2, 3, 444, 4, 5, "a", "b", "f"]
当然它也能像扩展运算符一样,将String字符串转换成数组
let str = 'hello world'
let arr = Array.from(str)
console.log(arr)//['h','e','l','l','o',' ','w','o','r','l','d']
这里要了解一个概念什么是类数组对象一般来说,类数组对象和数组没多大区别在操作上也是
let likeArr = {
'0':0,
'1':1,
'2':'aa',
'3':'bb',
'4':'cc',
'length':5
} //是不是和你控制台打印出来的数组对象很像甚至可以这样子做
console.log(likeArr[4])//cc
//我们可以用Array.from()将其转换成真正的数组
let arr = Array.from(likeArr)
console.log(arr)//[0, 1, "aa", "bb", "cc"]
在刚刚操作过程中我第一次在创建类数组对象时忘记定义length属性了,于是控制台报错了,说白了类数组对象都有一个length属性,如果没有则和普通对象没多大区别当然Array.from()也会控制台报错,当然扩展运算符是不能将类数组对象转换成数组的,但是Array.from()可以,对此我们可以用代码进行验证
let likeArr = {
length:3
}
console.log(Array.from(likeArr))//[undefined,undefined,undefined]
console.log(...likeArr)//Uncaught TypeError: Found non-callable @@iterator
我特地试了一下map数据类型
let map = new Map()
map.set('0','a').set('1','b')
let arr = Array.from(map)
console.log(arr) //[["0","a"],["1","b"]]
发现map数据类型可以被Array.from()转换但是转换成的是一个数组是一个[['键','值'],['键','值'],['键','值']]数组
类方法 of
Array.of()的作用是将一组值转换成数组,是不是和concat方法有点像,但是concat方法是作用于数组对象的,而且,如果传入的参数中包含数组是会将数组打散转换成独立值,而Array.of()不同,存入数组,转换成数组后该参数在返回值中还是数组在文档中阮一峰大神是这样子来说明的
这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
举个例子
Array.of(0,1,2,3,4)//[0,1,2,3,4]
Array.of(0)//[0]
//如果我们用传统的生成数组方式会是怎么样?
new Array() //[]
//传入一个参数
new Array(3)//生成一个长度为3的数组 [undefined,undefined,undefined]
//传入多个参
new Array(1,2)//[1,2]
从打印结果可知Array构造方法传入参数数量不同,返回的结果并不统一,而Array.of()却是出奇的统一,这弥补了Array构造方法的不足
在不传入参数时Array.of()会返回一个空数组
Array.of()//[]
数组对象copyWithin方法
引用文档中的介绍:数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。 该方法可接收三个参数:
- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数
let arr = [1,2,3,4,5,6,7,8,9]
console.log(arr.copyWithin(0,3,8))//[4, 5, 6, 7, 8, 6, 7, 8, 9]
let arr1 = [1,2,3,4,5,6,7,8,9]
console.log(arr1.copyWithin(0,5))//[6, 7, 8, 9, 5, 6, 7, 8, 9]
文档中有更详细的例子以下抄文档
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}
// 将2号位到数组结束,复制到0号位
let i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]
// 对于没有部署 TypedArray 的 copyWithin 方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]
数组对象的find/findIndex方法
超级好用的两个方法,因为很相似所以放到一起讲
find()用于找寻数组对象中第一个符合条件的值传入参数是一个回调函数由此可见是一个高阶函数,该方法类似数组对象的every()方法 some()方法 filter()方法,用于鉴别数组中的值,回调方法传入参数也类似都是必传value(值),可选index(索引),与arr(原数组)具体差别用实验来鉴别
let arr = [1,2,3,4,5,6,7,8,9]
//every()方法用于鉴别数组的所有元素是否符合要求并返回boolean
arr.every((value,index,arr)=>{
return value===7&&index===6
})//false
//some()方法用于鉴别数组中是否有符合要求的值并返回boolean
arr.some((value,index,arr)=>{
return value===7&&index===6
})//true
//filter()方法将数组中符合要求的值拼接成一个新数组并返回
arr.filter(value=>{
return value>3
})//[4, 5, 6, 7, 8, 9]
//find()方法返回数组中符合要求的第一个值
arr.find((value)=>{
return value>3
})//4
//若没有符合要求的值则返回undifined
arr.find((value)=>{
return value>100
})//undifined
findIndex的用法和find一样,但是返回值不同,find方法是返回符合条件的第一个值,若没有符合要求的值则返回undifined。findIndex则是返回符合条件的第一个值在数组中的位置,若没有符合要求的值则返回-1
arr.findIndex(value=>{
return value>3
})//3
arr.findIndex(value=>{
return value>100
})//-1
数组对象的fill方法
用于填充数组对象并返回新数组,会改变原数组例子如下
let arr = Array(3)//长度为3的数组 =>[undefined,undefined,undefined]
arr.fill(666) //[666,666,666]
console.log(arr) //[666,666,666]
let arr1 = [1,2,3,5,4]
arr1.fill(2333)//[2333, 2333, 2333, 2333, 2333]
迭代器遍历对象entries/keys/values 方法
entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
let arr = [1,2,3,4,5,6,7,8,9]
for (let index of arr.keys()) {
//返回key值
console.log(index); //0 1 2 3 4 5 6 7 8
}
for (let index of arr.values()){
//返回value值
console.log(index); //0 1 2 3 4 5 6 7 8
}
for (let index of arr.entries()){
//返回键值对
console.log(index) //[0,1],[1,2],[2,3]........
}
当然keys可以获取object对象的键并整合返回一个数组[key1,key2,key3,] values可以获取object对象的值并整合返回一个数组[value1,value2,value3] entries则可以获取object对象的键值数组 [[key1,value1],[key2,value2],[key3,value3]]
也能配合数组对象的其他高阶函数使用,比如我要创建一个包含过去7天Date的数组
let dateArr = [...Array(7).keys()].map(d=>new Date(Date.now()-d*1000*24*60))
//[Tue May 28 2019 13:27:00 GMT+0800 (中国标准时间), Tue May 28 2019 13:03:00 GMT+0800 (中国标准时间), Tue May 28 2019 12:39:00 GMT+0800 (中国标准时间), Tue May 28 2019 12:15:00 GMT+0800 (中国标准时间), Tue May 28 2019 11:51:00 GMT+0800 (中国标准时间), Tue May 28 2019 11:27:00 GMT+0800 (中国标准时间), Tue May 28 2019 11:03:00 GMT+0800 (中国标准时间)]
//或者说生成一个0到9的数组
let numArr = [...Array(10).keys()].map(n=>n)
//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
如果不使用Array.from()或者扩展运算符与高阶函数配合或者不用for of 循环进行配合则需要用到迭代器的next()方法进行往下操作
let arr = ['a','b','c','d','e']
let keysData = arr.keys()
console.log(keysData.next().value)//0
console.log(keysData.next().value)//1
console.log(keysData.next().value)//2
let valuesData = arr.values()
console.log(valuesData.next().value)//a
console.log(valuesData.next().value)//b
console.log(valuesData.next().value)//c
let entriesData = arr.entries()
console.log(entriesData.next().value)//[0,'a']
console.log(entriesData.next().value)//[1,'b']
console.log(entriesData.next().value)//[2,'c']
数组对象的 includes方法
非常好用的一个方法,用于判断数组中是否包含某个值若有则返回true,没有则返回false
let arr = [1,2,3,4,5]
arr.includes(2)//true
arr.includes(6)//false
该方法可以传入两个参数,第一个是用于判断是否存在的值,第二个是判断开始位置
let arr = [1,2,3,4,5]
arr.includes(2,3) //false
arr.includes(4,3) //true
数组对象的 flat/flatMap方法
flat()方法将数组中的数组打散生成一个新的数组,不改变原数组,不好理解是不是?!那还是看例子吧
let arr = [1,2,3,[4,5,6],7,[8,9]]
let newArr = arr.flat() //[1, 2, 3, 4, 5, 6, 7, 8, 9]
但是flat()方法只能打散一层数组,如果数组中嵌套的数组是多维数组则需要传入参数(Number类型),要打散几维数组则传几默认是1
let arr = [1,[2,[3,4,[5,6]]],7]
arr.flat(2) //[1,2,3,4,[5,6],7]
arr.flat(3) //[1,2,3,4,5,6,7]
如果不管数组中有几维数组都要将数组打散成一维数组的话可以传入关键字Infinity
let arr = [1,[2,[3,[4,[5,[6,[7,[8]]]]]]],9]
arr.flat(Infinity)//[1,2,3,4,5,6,7,8,9]
flatMap()方法与flat()类似,都能打散数组,但是flatMap()只能打散一层并且flatMap()与map类似可以传入一个回调函数作为参数,并且返回一个新数组
let arr = [1,[2,[3,[4,[5,[6,[7,[8]]]]]]],9]
let mapArr = arr.flatMap(i=>{
return typeof(i)
})//["number", "object", "number"]
flatMap()方法回调函数参数也与map()方法回调函数参数相同都可以传入value(值,必填),key(索引,选填),arr(原数组,选填)
转载自:https://juejin.cn/post/7142493364535951396