数组操作的十八般武艺一网打尽!

153 阅读9分钟

数组操作方法

一、shift和unshift

  • shift:删除数组中的第一个元素
  • unshift:在数组的开头添加一个或更多的元素

代码实现

   let array = ["a", "d", "v", "c","g"]
   console.log(array.pop())
   console.log(array)
   console.log(array.push('j','k'))
   console.log(array) 

运行结果

shift和unshift.png

二、pop和push

  • pop:删除数组中的最后一个元素
  • push:在数组的末尾添加一个或更多的元素

代码实现

   let array = ["a", "d", "v", "c","g"]
   console.log(array.pop())
   console.log(array)
   console.log(array.push('j','k'))
   console.log(array) 

运行效果

pop和push.png

三、delete

delete:通过下标删除数组,删除后对应下标变为空,数组整体长度不变。

代码示例

   let arr = [1,2,3,4,5];
   delete arr[2];
   console.log(arr);

运行效果

delete.png

注意: 此时输出arr[2]的结果为undefined

delete2.png

四、splice()

splice:希望删除元素后,元素的位置会被后继的元素填补,数组的长度变短。 这个时候,我们就需要splice()方法。且需要提前说明的是,splice()方法的功能相当丰富,并非只能删除元素

1、删除一个元素

设置splice两个参数,第一个为起始下标。

代码实现

       let arr = [1,2,3,4,5]
       arr.splice(0,1);//删除掉第一个元素 1
       console.log(arr)

运行效果

splice1.png

2、删除多个元素

删除多个元素和删除一个元素用法相同,只需要将第二个参数改为指定数量就可以了。

代码实现

    let arr = [1,2,3,4,5];
    arr.splice(0,3);//删除前三个元素
    console.log(arr);//[4,5]

运行效果

splice2.png

3、截断数组

如果我们只提供一个参数start,那么就会删除数组start位置后面的所有元素。

代码实现

    let arr = [1,2,3,4,5]
    arr.splice(2);//删除从下标为2以及后面的所有元素
    console.log(arr);//[1,2]

运行效果

splice3.png

4、元素替换

如果我们提供了超过两个参数,那么就可以替换数组元素

代码展示

    let arr = [1,2,3,4,5];
    arr.splice(0,2,'a','b,'c');
    console.log(arr);//['a','b,'c',3,4,5]

执行效果

splice4.png

5、元素插入

如果我们把第二个参数(删除数量)改为0,那么就可以只插入元素,不删除元素

代码展示

    let arr = [1,2,3]
    arr.splice(0,0,'x','y','z')
    console.log(arr);//['x','y','z'1,2,3]

执行效果

splice5.png

6、返回值

splice()函数可以被删除的元素数组。

代码展示

    let arr = [1,2,3,4,5]
    let res = arr.splice(0,3,'x','y')
    console.log(arr)//['x','y',4,5]
    console.log(res)//[1,2,3]

执行效果

splice6.png

7、负索引

我们可以使用负数指示开始操作元素的位置(-1表示从最后一个开始)

代码展示

    let arr = [1,2,3,4,5]
    arr.splice(-1,1,'x','y','z')
    console.log(arr)//[1,2,3,4,'x','y','z']

执行效果

splice7.png

五、slice()

slice()方法可以截取指定范围的数组,语法如下:

arr.slice([start],[end])

返回一个新数组,新数组从start开始,到end结束,但是不包括end

代码展示

    let arr = [1,2,3,4,5]
    console.log(arr.slice(2,5))//[3,4,5]
    console.log(arr.slice(1,3))//[2,3]

执行效果

slice.png

slice()同样可以使用负数下标

代码展示

    let arr = [1,2,3,4,5]
    console.log(arr.slice(-3))//[3,4,5]
    console.log(arr.slice(-5,-1))//[1,2,3,4]

执行效果

slice2.png

注意

如果只为slice()方法提供一个参数,就会和splice()一样截断到数组末尾。

六、concat()

concat()函数可以将多个数组或者其他类型的值拼接称一个长数组

arr.concat(e1, e2, e3)

以上代码将返回一个新的数组,新数组由arr拼接e1e2e3而成。

代码展示

    let arr = [1,2,3]
    console.log(arr.concat([4,5],6,7,[8,9]))

执行效果

concat.png

注意: 即使它们看起来和对象一样,仍然会被作为一个整体插入到数组中。

代码展示

    let arr = [1,2]
    let obj = {1:'1',2:2}
    console.log(arr.concat(obj))

执行效果

concat2.png

但是,如果对象具有Symbol.isConcatSpreadable属性,就会被当作数组处理。

代码展示

    let arr = [1,2]
    let obj = {0:'x',
               1:'y',
               [Symbol.isConcatSpreadable]:true,
               length:2      
    }
    console.log(arr.concat(obj))

执行效果

concat3.png

七、forEach()

遍历整个数组,为每个数组元素提供一个操作函数

代码展示

    let arr1= [1,2,3,4,5]
    arr1.forEach(itm)=>{
        console.log(itm)
    })
    
    let arr = [1,2,3,4,5]
    arr.forEach((itm,idx,array)=>{
        console.log(`arr[${idx}]`+`是数组`+` [${array}] `+`中的`+` ${itm}`)
    })

执行效果

foEach.png

八、indexOf、lastIndexOf、includes

类似于字符串,indexOflastIndexOfincludes可与查询数组中指定元素的下标

  • arr.indexOf(itm,start):从start位置开始搜索itm,如果找到返回下标,否则返回-1;

  • arr.lastIndexOf(itm,start):倒序查找整个数组,直至start处,返回第一个查到的下标(也就是数组最后一个匹配项),找不到返回-1;

  • arr.includes(itm,start):从start位置开始搜索itm,找到返回true,否则返回false;

代码展示

    let arr = [1,2,3,4,5,6,"7","8","9",0,0,true,false]
    console.log(arr.indexOf(0))//9
    console.log(arr.lastIndexOf(0))//10
    console.log(arr.includes(10))//false
    console.log(arr.includes(9))//false

执行效果

includes.png

NaN的处理

NaN是一个特殊的数字,三者在处理NaN有细微差别

代码展示

    let arr = [NaN,1,2,3,NaN]
    console.log(arr.includes(NaN))//true
    console.log(arr.indexOf(NaN))//-1
    console.log(arr.lastIndexOf(NaN))//-1
    // 产生这种结果的原因和`NaN`本身的特性有关,即`NaN`不等于任何数字,包括他自己。

执行结果

includes2.png

九、find、findIndex

在编程过程中常常会遇到对象数组,而对象是不能直接使用===比较的,个时候就要使用findfindIndex方法,语法如下:

    let result = arr.find(function(item,idx,array){
        //item数组元素
        //idx元素下标
        //array数组本身
        //传入一个判断函数,如果该函数返回true,就返回当前对象item
    })

举个栗子:假如我们需要查找name属性等于huge的对象

代码展示

    let arr =[
        {id:1,name:'huge'},
        {id:2,name:'jindong'},
        {id:3,name:'liangchaowei'},
    ]
    let huge = arr.find(function(item,idx,array){
        if(item.name == 'huge')return true;
    })
    console.log(huge)
    // 果没有符合条件的对象,就回返回undefined

执行效果

find.png

arr.findIndex(func)的用途和arr.find(func)几乎相同,唯一不同的地方在于,arr.findIndex返回符合条件对象的下标而不对象本身,找不到返回-1

十、filter

findfindIndex只能查找一个满足要求的对象,如果一个数组中存在多个满足要求的对象,就需要使用filter方法,语法如下:

    let results = arr.filter(function(itm,idx,array){
        //和find的用法相同,不过会返回符合要求的对象数组
        //找不到返回空数组
    })

举个栗子

代码展示

    let arr =[
        {id:1,name:'huge'},
        {id:2,name:'jindong'},
        {id:3,name:'liangchaowei'},
    ]
    let res = arr.filter(function(itm,idx,array){
        if(itm.name == 'huge' || itm.name == 'jindong')return true;
    })
    console.log(res)

执行效果

filter.png

十一、map

arr.map方法可以对数组的每个对象都调用一个函数,然后返回处理后的数组,这是数组最有用的、最重要的方法之一。语法如下:

    let arrNew = arr.map(function(itm,idx,array){
        //返回新的结果
    })
    

举个栗子:返回字符串数组对应的长度数组

代码展示

    let arr = ['I','am','a','handsomeboy']
    let arrNew = arr.map((itm)=>itm.length)
    console.log(arrNew)

执行效果

map.png

十二、sort

arr.sort对数组进行原地排序,并返回排序后的数组,但是,由于原数组已经发生了改变,返回值实际上没有什么意义。所谓原地排序,就是在原数组空间内排序,而不是新建一个数组

举栗子

1、字母排序

代码展示

    let arr = ['a','c','b']
    arr.sort()
    console.log(arr)

执行效果

sort1.png

注意

默认情况下sort方法是以字母序进行排序的,也就是适用于字符串排序,如果要排列其他类型的数组,需要自定义比较方法

2、数字排序

代码展示

    let arr = [1,3,2]
    arr.sort(function(a,b){
        if(a > b)return 1;
        if(a < b)return -1;
        return 0;
    })

执行效果

sort2.png

sort函数内部采用了快速排序算法,也可能是timsort算法,但是这些我们都不需要关心,我们只需要关注比较函数就可以了。

比较函数可以返回任何数值,正数表示>,负数表示<0表示等于,所以我们可以简化数字比较方法:

    let arr = [1,3,2]
    arr.sort((a,b)=> a - b)

如果想要逆序排列只需要交换一下ab的位置既可以了:

    let arr = [1,3,2]
    arr.sort((a,b)=> b - a)

3、字符串排序

别忘了字符串比较要使用str.localeCompare(str1)方法喔

代码展示

    let arr = ['asdfas','success','failures']
    arr.sort((a,b)=>a.localeCompare(b))

执行效果

sort3.png

十三、reverse

arr.reverse用于逆序数组

代码展示

    let arr = [1,2,3]
    arr.reverse()
    console.log(arr)

执行效果

reserve.png

十四、str.split()和arr.join()

还记得字符串分割函数吗?字符串分割函数可以将字符串分割成一个字符数组:

    let str = 'xiaoming,xiaohong,xiaoli'
    let arr = str.split(',')//['xiaoming','xiaohong','xiali']

冷门知识,split函数有第二个参数,可以限制生成数组的长度

    let str = 'xiaoming,xiaohong,xiaoli'
    let arr = str.split(',',2)//['xiaoming','xiaohong']

arr.join()方法用途和split方法相反,可以将一个数组组合成一个字符串。

举个栗子

代码展示

    let arr = [1,2,3]
    let str = arr.join(';')
    console.log(str)

执行效果

join.png

十五、reduce、reduceRight

arr.reduce方法和arr.map方法类似,都是传入一个方法,然后依次对数组元素调用这个方法,不同的地方在于,app.map方法在处理数组元素时,每次元素调用都是独立的,而arr.reduce会把上一个元素的调用结果传到当前元素处理方法中。语法如下:

    let res = arr.reduce(function(prev,itm,idx,array){
        //prev是上一个元素调用返回的结果
        //init会在第一个元素执行时充当上一个元素调用结果
    },[init])

如何实现一个数字组成的数组元素和呢?map是没有办法实现的,这个时候就需要使用arr.reduce

代码展示

    let arr = [1,2,3,4,5]
    let res = arr.reduce((sum,itm)=>sum+itm,0)
    console.log(res)

执行效果

reduce.png

arr.reduceRightarr.reduce用途相同,只不过从右往左对元素调用方法。

十六、Array.isArray()

数组是对象的一种特例,使用typeof无法准确的分辨二者的区别

    console.log(typeof {})//object
    console.log(typeof [])//object

二者都是对象,我们需要使用Array.isArray()方法进一步做判断

代码展示

    console.log(Array.isArray({}))//false
    console.log(Array.isArray([]))//true

执行效果

isArray.png

十七、some、every

arr.some(func)arr.every(func)方法用于检查数字,执行机制和map类似

some

对每个数组元素执行传入的方法,如果方法返回true,立即返回true,如果所有的元素都不返回true,就返回false

every

对数组的每个元素执行传入的方法,如果所有元素都返回true,则返回true,否则返回false

举个例子

代码展示

    let arr = [1,2,3,4,5]
    //判断数组是否存在大于2的元素
    console.log(arr.some((itm)=>{
        if(itm > 2)return true;
    }))

    //判断是否所有的元素都大于2
    console.log(arr.every((itm)=>{
        if(itm > 2)return true;
    }))

执行效果

some every.png

十八、this.Arg

在所有的数组方法中,除了sort,都有一个不常用固定参数thisArg,语法如下:

    arr.find(func,thisArg)
    arr.filter(func,thisArg)
    arr.map(func,thisArg)

如果我们传入了thisArg,那么它就会在func中变为this

这个参数在常规情况下是没什么用处的,但是如果func是一个成员方法(对象的方法),而且方法中使用了this那么thisArg就会非常有意义。

举个例子

代码展示

    let obj = {
        num : 3,
        func(itm){
            console.log(this)
            return itm > this.num;//查找大于3的数字
        }
    }
    let arr = [1,2,3,4,5,6,7]
    let newArr = arr.filter(obj.func,obj)
    console.log(newArr)

执行效果

thisArg.png

注意

这里我们可以看到,func中输出的this就是我们传入的thisArg值。

如果我们使用对象成员方法,同时不指定thisArg的值,就会造成thisundefined,从而导致程序错误。

总结

作为一种非常常用的引用类型,其中包含很多的方法,当我们熟练掌握这些方法之后,在一些复杂的功能上就能解决起来游刃有余。