JS中数组常用方法

167 阅读18分钟

前言

在进行日常开发中,很多时候需要使用到数组,如接收到后端传输的数据时。在这个时候需要进行一些对数组的操作,JS提供了很多的api操作,平时也没有对数组api进行总结,在使用的时候经常要去看文档才知道这个方法是什么意思,趁最近不怎么需要写项目,总结一下常用的数组api的使用。

创建数组

JAVA中,创建数组有两种方法,显式创造:通过[]直接赋值一个数组;隐式创造:通过构造器给数组赋值。在JS中,这两种方法也同样适用。

    // 字面量创建
    let arr = [1,2,3]//[1,2,3]
    // 构造器
    // new Array === Array
    let arr1 = Array()//[]
    let arr2 = Array(3)//[]
    let arr3 = Array(1,2,3)//[1,2,3]

字面量创建对象这种方法是比较简单的,也是经常使用的。通过构造器创建一个数组这种用的较少,Array() 中如果只有一个参数,那么这个参数表示这个数组的长度,如果参数大于1个时,那参数就是数组的值了。

ES6

Array.of()返回由参数值组成的数组

定义:返回由所有参数的值组成的数组,如果没有参数就返回一个空数组

    let arr = Array.of(1)//[1]
    let arr1 = Array.of(1,2,3)//[1,2,3]

Array.of() 的出现主要是为了避免像Array() 中只有一个参数时,会把参数当成数组长度的情况。

Array.from()将两类对象转化为真正的数组

Array.from()是对一个类似数组或可迭代对象创建一个新的,浅拷贝数组的实例。
定义:将两类对象转化为真正的数组,不改变原数组,返回一个新的数组
语法:Array.from(arrayLike, mapFn, thisArg)
参数:
arrayLike(必选):想要转换成数组的伪数组对象或可迭代对象。
mapFn(可选):类似数组的map方法,对每个元素进行处理,将处理后的值放入返回的数组。
thisArg(可选):执行回调函数时mapFn绑定的this对象。

    let obj = {0: 'a', 1: 'b', 2: 'c', length: 3}
    let arr = Array.from(obj)//[a,b,c]
    let arr1 = Array.from('hello')//[h,e,l,l,o]
    let arr2 = Array.from(new Set(['a','b']))//[a,b]

数组原型所提供的方法

数组原型所提供的方法大致分为两类:一类是会改变原数组的值,另一类是不会改变原数组

不会改变原数组的值

不会改变原数组的方法有8个。

  1. slice
  2. join
  3. toLocateString
  4. toStrigin
  5. cancat
  6. indexOf
  7. lastIndexOf
  8. includes

slice()浅拷贝数组元素

定义:返回一个从开始到结束 (不包括结束) 的一个数组,且原数组不会被修改,注:浅拷贝
语法:

array.slice(begin, end)

参数:
begin(可选):索引数值,接受负值,从该索引处开始提取原数组中的元素,默认值为0。 end(可选):索引数值 (不包括),接受负值,在该索引处前结束提取原数组元素,默认值为数组末尾。
示例:

    let arr = ['h','e','l','l']
    let a = arr.slice(0,1)//a: [h]  
    a[0] = '2'
    console.log(arr,a);//arr: [h,e,l,l] a:[2]

slice方法所拷贝的数组是浅拷贝下来的数组,浅拷贝下来的,普通数据类型不会有什么关联,但当存在引用数据类型时,改变一个数组的值,另一个数组也会变。

    let arr = [{name : 'zzz'}]
    let a = arr.slice()
    console.log(arr,a); //arr: [{name: zzz}] a: [{name:zzz}]
    a[0].name = 'hhh'
    console.log(arr,a); //arr: [{name: hhh}] a: [{name: hhh}]

slice浅拷贝,对于引用数据类型,浅拷贝只是将拷贝后的数组的指针指向原数组,当改变一个数值的值,另一个数组的值会跟着改变。

join()数组转字符串

定义:join()方法用于把数组中的所有元素通过指定的分隔符进行分隔放入一个字符串返回生成的字符串
语法:

array.join(str)

参数:
str(可选):指定要使用的分隔符,默认使用逗号作为分隔符。
示例:

    let arr = [1,2,3,4,5]
    let a = arr.join()// a: 1,2,3,4,5
    let b = arr.join('+')// b:1+2+3+4+5

此方法只适用于非引用对象的数组,当数组为数组或对象时不太适用。

    let arr = [['zzz',23],'hhh']
    let a = arr.join()// a: zzz,23,hhh 
    let arr1 = [{name: 'zzz',age: 22},'hhh']
    let b = arr1.join()// b:[object Object],hhh

当调用join() 方法的数组里面是数组时,里面的数组也会同时调用join() 方法,当调用join() 方法的数组里面是对象时,对象会被转换成 [object Object] 字符串

toLocalString()数组转字符串

定义:返回一个表示数组元素的字符串。该字符串由数组中的每个元素的toLocaleString()返回值经调用join()方法连接组成
语法:

array.toLocaleString()

参数:无
示例:

    let arr = [{name: 'zzz'},23,'abcd',new Date()]
    let a = arr.toLocaleString()// a: [object Object],23,abcd,2022/11/23 16:55:42

在上述代码中,数组调用*toLocaleString()*方法,数组中的每个元素都会调用自己的 toLocaleString() 方法,对象调用对象的 toLocaleString() 方法,Date调用Date的 toLocaleString() 方法。

toString()数组转字符串

定义:toString()方法可以把数组转换为逗号连接起来的字符串。
语法:

array.toString()

参数:无
示例:

    let a = ['zzz','hhh'].toString()//zzz,hhh
    let b = ['zzz','hhh'] + 'www'//zzz,hhhwww

toString() 方法的效果与使用 join() 方法差不多,但 *toString() *方法无法自定义分隔符,所以我们更多的使用 join() 方法。
当字符串和数组操作时,js会调用这个方法将数组自动转换成字符串

cancat()连接数组

定义:该方法用于合并两个或多个数组,返回一个新的数组。
语法:

let newArray = oldArray.cancat(arrayX,arrayX,...,arrayX)

参数:
arrayX (必选):该参数可以是具体的值,也可以是数组对象。可以有任意多个arrayX
示例:

    let a = [1,2,3]
    let b = [4,5,6]
    let newArray = a.concat(b) // [1,2,3,4,5,6]
    let c = [7,8,9]
    let newArray1 = a.concat(b, c) // [1,2,3,4,5,6,7,8,9]
    let newArray2 = a.concat('添加元素',b,c,'再加一个元素')
    let d = [1,2]
    let f = [3,[4]]
    let newArray3 = d.concat(f) // [1,2,3,[4]]

在ES6中,提出了拓展运算符: ... 这个语法比cancat() 来说,使用起来更简单更简洁。
示例:

    let a = [1,2,3,4]
    let b = [4,...a,4,5] //4,1,2,3,4,4,5

indexOf()查找数组是否存在某个元素,返回下标

定义:返回在数组汇总可以找到一个给定元素的第一个索引,如果不在则返回 -1
语法:

array.indexOf(searchElement, fromIndex)

参数:
searchElement(必选):被查找的元素
fromIndex (可选):开始查找的位置(不能大于等于数组的长度,否则返回-1),接受负值,默认值为0。

注:
数组的indexOf搜索与字符串的indexOf不一样,数组的indexOf使用严格相对 === 搜索元素,数组的元素要完全匹配才能搜索成功。

indexOf()不能识别NaN
示例:

    let a = ['你好',2,3,NaN]
    console.log(a.indexOf('你'));// -1
    console.log(a.indexOf('NaN'));// -1
    console.log(a.indexOf('你好'));// 0

lastIndexOf() 查找指定元素在数组中的最后一个位置

定义:返回指定元素在数组中的最后一个索引,如果不存在则返回 -1 (从数组后面往前查找)
语法:

arr.lastIndexOf(searchElement, fromIndex)

参数:
searchElement(必选):被查找的元素。
fromIndex(可选):逆向查找开始位置,默认值为数组长度-1。如果省略参数将从字符串的最后一个字符开始搜索。

关于fromIndex:

  1. 正值。如果该值大于或等于数组的长度,则整个数组会被查找。
  2. 负值。将其视为从数组末尾向前的偏移。
  3. 负值。其绝对值大于数组长度,则方法返回-1,即数组不会被查找。

示例:

    let a = ['zz',4,'hh',1,2,'hh',3,4,5,'hh']
    let b = a.lastIndexOf('hh',4)//2 从下标4的元素开始往前找,返回的元素下标2
    let c = a.lastIndexOf('hh',100)//9 大于或等于整个数组的长度,查找整个数组
    let d = a.lastIndexOf('hh',-11)//-1 数组不会被查找
    let e = a.lastIndexOf('hh',-9)//-1 从第2个元素往前查找,没有找到,返回-1

includes() 查找数组是否包含某个元素,返回布尔值

定义:返回一个布尔值,表示某个数组是否包含给定的值。 语法:

array.includes(searchElement, fromIndex = 0)

参数:
searchElement(必选):被查找的元素。
fromIndex(可选):默认值为0,参数表示搜索的起始位置,接受负值。正值超过数组长度,数组不会被搜索,返回false。负值绝对值超过数组长度,重置从0开始搜索。

includes方法是为了弥补indexOf方法的缺陷而出现的

  1. indexOf方法不能识别NaN
  2. indexOf方法检查是否包含某个值不够语义化,需要判断是否不等于*-1*,表达不够直观。

示例:

    let a = ['zz','hh',1,NaN]
    let b = a.includes(NaN) //true 可以识别NaN
    let c = a.includes('hh',100) //false 超过数组长度,不搜索
    let d = a.includes('hh',-3) // true 从倒数第3个元素开始搜索
    let e = a.includes('hh',-100) // true 负数的绝对值超过数组长度,搜索整个数组

改变原数组的方法(9个):

  1. splice
  2. sort
  3. pop
  4. shift
  5. push
  6. unshift
  7. reverse
  8. copyWithin
  9. fill

splice()添加/删除数组元素

定义:向数组中添加/删除元素,不返回新数组。
语法:

array.splice(index, howmany, item1, ... ,itemX)

参数:
index(必选):整数,规定添加/删除元素的位置,负数表示从数组后面开始。
howmany(可选):要删除元素的数量。设置为0则不会删除项目。
item1, ..., itemX(可选):向数组添加新的元素。

示例:
删除元素

    let a = [1,2,3,4,5,6,7]
    a.splice(0,3)//4,5,6,7
    let b = [1,2,3,4,5,6,7]
    b.splice(-1,3)//1,2,3,4,5,6 从最后一个元素开始删除,因为只有7,所以只删除7

添加

    let a = [1,2,3,4,5,6,7]
    a.splice(0,0,'添加1','添加2')// "添加1","添加2",1,2,3,4,5,6,7
    let b = [1,2,3,4,5,6,7]
    b.splice(-1,0,'添加1','添加2')// 1,2,3,4,5,6,'添加1','添加2',7

删除并添加

    let a = [1,2,3,4,5,6,7]
    a.splice(0,3,'添加')//'添加',4,5,6,7 从数组下标0开始,删除3个元素,并添加'添加'
    let b = [1,2,3,4,5,6,7]
    b.splice(-2,3,'添加')//1,2,3,4,5,'添加' 从数组倒2个元素开始,删除三个元素,再添加'添加'

sort() 数组排序

定义:对数组元素进行排序,并返回这个数组,默认是按字母升序排列。
参数:
默认情况下 sort() 方法没有传比较函数的话,默认按字母升序,如果不是元素不是字符串的话,会调用toString() 方法将元素转化为字符串的Unicode位点,然后再比较字符。

示例:

    let a = ['Banana', 'Orange', 'Apple', 'Mango']
    a.sort()//'Apple','Banana','Mango','Orange'
    // console.log(a);
    let b = [10,1,3,20,25,8]
    b.sort()//1,10,20,25,3,8

当排序的数组都为字符串时,sort() 方法可以成功排序,但当数组中的元素为数字时或是对象时,不能直接使用该方法。

比较函数的两个参数:
sort方法比较函数有两个默认参数,要在函数中接收这两个参数,这两个参数是数组中两个要比较的元素,通常我们用a和b接收两个将要比较的元素:

  1. 若比较函数返回值<0,那么a将排到b的前面;
  2. 若比较函数返回值=0,那么a和b相对位置不变;
  3. 若比较函数返回值>0,那么b排在a的前面。

sort排序常见的用法:
数组元素为数字时:

    let array = [10,1,3,4,2,11,5]
    // 升序 a-b<0 a将排到b的前面,按照a的大学来排序
    // 比如被减数a是10,减数是20 10-20 < 0 被减数a(10)在减数b(20)前面
    array.sort(function(a,b) {
        return a-b
    })
    console.log(array); //1,2,3,4,5,10,11
    // 降序 被减数和减数交换 20-10>0 
    array.sort(function (a,b) {
        return b-a
    })
    console.log(array);//11,10,5,4,3,2,1

数组元素为对象时:

    let array = [{id:10,age:2},{id:5,age:1},{id:6,age:10},{id:9,age:6},{id:2,age:8},{id:10,age:9}]
    array.sort(function (a,b) {
        if (a.id === b.id) {// 如果id的值相等,按照age的值降序排列
            return b.age - a.age
        }else {// 如果id的值不相等,按照id的值升序
            return a.id - b.id
        }
    })
    console.log(array);
    //[{id:2,age:8},{id:5,age:1},{id:6,age:10},{id:9,age:6},{id:10,age:9},{id:10,age:2}]

pop() 删除一个数组中的最后一个元素

定义:删除一个数组中的最后一个元素,并且返回这个元素。
参数: 无
示例:

    let a = [1,2,3]
    a.pop()
    console.log(a);//1,2

shift()删除数组的第一个元素

定义:删除数组的第一个元素,并返回这个元素。 参数:无
示例:

    let a = [1,2,3]
    a.shift()
    console.log(a);// 2,3

unshift()向数组开头添加一个或更多元素

定义:向数组的开头添加一个或更多元素,并返回新的长度。
参数:item1,item2,...,itemX 示例:

    let a = [1,2,3]
    a.unshift('开头')
    console.log(a);//'开头',1,2,3

reverse() 颠倒数组中元素的顺序

定义:用于颠倒数组中元素的顺序
参数:无

    let a = [1,2,3]
    a.reverse()
    console.log(a);//3,2,1

copyWithin() 指定位置的成员复制到其他位置

定义:在当前数组内部,将指定位置的成员复制到其他位置,并返回这个数组。
语法:

array.copyWithin(target,start = 0, end = this.length)

参数:
三个参数都是数值,如果不是,会自动转换为数值。
target(必选):从该位置开始替换数据。如果为负值,表示倒着。
start(可选):从该位置开始读取数据,默认为0。如果为负数,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。使用负数可以从数组结尾处规定位置。

示例:

    let a = [1,2,3,4,5]
    a.copyWithin(0,-2,-1)
    console.log(a);//4,2,3,4,5  从第一位开始替换数据,从倒2位开始读取数据,读取到最后一位,不包括最后一位  
    let b = ['zz','hh','cc','vv','bb','nn']
    b.copyWithin(2,3,5)
    console.log(b);// zz,hh,vv,bb,bb,nn

fill()填充数组

定义:使用给定值,填充一个数组。
语法:

array.fill(value,start,end)

参数:
value(必选):要填充数组的值
start(可选):开始填充数组的索引(默认为0)
end(可选):停止填充数组的索引(默认为array.length)
示例:

    let a = ['a','b','c']
    a.fill(1)
    console.log(a);// 1,1,1 如果只填第一个参数,那么会全部替换
    let b = ['a','b','c']
    b.fill(7,1,2)
    console.log(b);// 'a',7,'b'

遍历数组的方法

在JS中遍历数组并且不会改变原始数组的方法总共有12个:

ES5:

  1. forEach
  2. every
  3. some
  4. filter
  5. map
  6. reduce
  7. reduceRight

ES6:

  1. find
  2. findIndex
  3. keys
  4. values
  5. entries

forEach

定义:按升序为数组中含有效值的每一项执行一次回调函数。
语法:

array.forEach(function(currentValue, index, arr),thisValue)

参数:
function(必选):数组中每个元素需要调用的函数
thisValue(可选):当执行回调函数时this绑定对象的值,默认为undefined
回调函数的参数:
currentValue(必选):数组当前元素的值
index(可选):当前元素的索引值
arr(可选):数组对象本身

示例:

    let a = [1,2, ,3] //倒二个元素是空的,不会遍历(undefined,null会被遍历)
    let obj = {name: 'zzz'}
    let result = a.forEach(function(value,index,array){
        a[3] = '改变的元素'
        a.push('添加到末尾,不会被遍历')
        console.log(value);//1,2,改变元素
        console.log(this.name);// 打印三次zzz
        return value// return只能结束本次回调,会执行下次回调
        console.log('不会执行,因为return会执行下一次循环回调');
    },obj)
    console.log(result)// 即使ruturn了一个值,也还是返回undefined
    // 回调函数也接受箭头函数,但回调函数无法改变箭头函数this指向

注:

  1. 对于空数组是不会执行回调函数的
  2. 对于在迭代过程中删除的元素或者空元素会跳过回调函数
  3. 遍历次数在第一次循环前就会确定,再添加到数组中的元素不会被遍历
  4. 如果已经存在的值被改变,则传递给callback的值是遍历到他们那一刻的值
  5. 无法中途退出循环,只能用return退出本次回调,进行下一次回调
  6. 它总是返回undefined的值,即使你return了一个值

every 检测数组所有元素是否都符合判断条件

定义:用于检测数组所有元素是否都符合函数定义的条件
语法:

array.every(function(currentValue, index, arr), thisValue)

参数:
function(必选):数组中每个元素需要调用的参数。
thisValue(可选):当执行回调函数时this绑定对象的值,默认值为undefined 回调函数的参数:
currentValue(必选):数组当前元素的值。
index(可选):当前元素的索引值。
arr(可选):数组对象本身。

示例:

    function isBigEnough(element,index,array) {
        return element >= 10
    }
    let a = [12,5,8,130,44]
    console.log(a.every(isBigEnough));//false
    
    let b = [12,54,18,130,44]
    console.log(b.every(isBigEnough));//true
  1. 如果数组中检测到有一个元素不满足,则整个表达式返回false,且剩余的元素不会再进行检测。
  2. 如果所有元素都满足条件,则返回true

some 数组中的是否有满足判断条件的元素

定义: 数组中是否有满足判断条件的元素
语法:

array.some(function(currentValue, index, arr), thisValue)

参数:
function(必选):数组中每个元素需要调用的参数。
thisValue(可选):当执行回调函数时this绑定对象的值,默认为undefined。
回调函数的参数:
currentValue(必选):数组当前的元素值。
index(可选):当前元素的索引值。
arr(可选):数组对象的本身。
示例:

    function isBigEnough(element) {
        return (element >= 10)
    }
    let a = [2,5,8,1,4]
    console.log(a.some(isBigEnough));//false
    let b = [12,5,8,1,4]
    console.log(b.some(isBigEnough));//true
  1. 如果有一个元素满足条件,则表达式返回true,剩余的元素不会再执行检测。
  2. 如果没有满足条件的元素,则返回false

filter 过滤原始数组,返回新的数组

定义:返回一个数组,其包含通过所提供函数实现的测试的所有元素。
语法:

let array = arr.filter(function(currentValue, index, arr), thisArg)

参数:
function(必选):数组中每个元素需要调用的函数。
thisValue(可选):当执行回调函数时this绑定对象的值,默认值为undefined
回调函数参数:
currentValue(必选):数组当前元素的值
index(可选):当前元素的索引值
arr(可选):数组对象本身

示例:

    let a = [21,33,11,20]
    let result = a.filter(function (value) {
        return value >= 18
    })
    console.log(result);//21,33,20

map 对数组中的每个元素进行处理,返回新的数组

定义:创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数返回的结果。
语法:

let array = arr.map(function(currentValue, index, arr),thisArg)

参数:
function(必须):数组中每个元素需要调用的函数
thisValue(可选):当执行回调函数时this绑定对象的值,默认值为undefined
回调函数的参数:
currentValue(必选):数组当前元素的值
index(可选):当前元素的索引值
arr(可选):数组对象本身

示例:

    let a = ['1','2','3','4']
    let result = a.map(function(value){
        return value + '新数组的新元素'
    })
    console.log(result);//'1新数组的新元素','2新数组的新元素','3新数组的新元素','4新数组的新元素'

reduce 为数组提供累加器,合并为一个值

定义: 对累加器和数组中的每个元素(从左到右)应用一个函数,最终合并为一个值。
语法:

array.reduce(function(total, currentValue, index, arr),initiaValue)

参数:
function(必选):数组中每个元素需要调用的函数
initialValue(可选):传递给函数的初始值

示例:

    let sum = [0,1,2,3]
    let x = sum.reduce(function (a,b) {
        return a+b
    },0)
    console.log(x); //6 

    let flattened = [[0,1],[2,3],[4,5]]
    let y = flattened.reduce((a,b) => a.concat(b),[])
    console.log(y);//[0,1,2,3,4,5]

回调第一次执行时:

  1. 如果initialValue在调用reduce时被提供,那么第一个total将相等于initialValue,此时currentValue等于数组中的第一个值。
  2. 如果initialValue未被提供,那么total等于数组中的第一个值,currentValue等于数组中的第二个值。此时如果数组为空,那么将抛出TypeError
  3. 如果数组仅有一个元素,并且没有提供initialValue,或提供了initialValue但数组为空,那么回调不会被执行,数组的唯一值将被返回。

reduceRight 从右至左累加

这个方法除了与reduce执行的方向相反外,其他完全与其一致。

find() 找出第一个符合条件的数组成员

定义: 用于找出第一个符合条件的数组成员,并返回该成员,如果没有符合条件的成员,则返回undefined
语法:

let array = arr.find(function(currentValue, index, arr), thisArg)

参数:
function(必选):数组中每个元素需要调用的函数
thisValue(可选):当执行回调函数时,this绑定对象的值,默认值为undefined
回调函数的参数:
currentValue(必选):数组当前元素的值
index(可选):当前元素的索引值
arr(可选):数组对象本身

示例:

    let a = [1,2,3,-2,NaN]
    let b = a.find(n => Object.is(NaN,n))
    console.log(b);//NaN

该方法可以识别NaN

findIndex()找出第一个符合条件的数组成员的下标

定义: 返回第一个符合条件的数组成员的位置, 如果所有成员都不符合条件,则返回-1
语法:

let array = arr.findIndex(function(currentValue,index,arr),thisArg)

参数:
function(必选):数组中每个元素需要调用的函数
thisArg(可选):当执行回调函数时this绑定对象的值,默认值为undefined
回调函数的参数:
currentValue(必选):数组当前元素的值
index(可选):当前元素的索引值
arr(可选):数组对象本身

示例:

    let a = [1,3,-2,10]
    let b = a.findIndex(n => n < 0)
    console.log(b);//2

find一样,该方法也可以识别到NaN

keys(),values(),netries()遍历键名,遍历键值,遍历键名+键值

定义:三个方法都返回一个新的Array lterator对象,对象根据方法不同包含不同的值。
语法:

array.keys() array.values() array.entries()

参数:无
示例:

    for(let index of ['a','b'].keys()) {
        console.log(index);//0,1
    }
    for(let elem of ['a','b'].values()){
        console.log(elem);//a,b
    }
    for(let [index,elem] of ['a','b'].entries()){
        console.log(index,elem);//0'a',1'b'
    }