操作数组的方法

61 阅读11分钟

改变原数组的方法

push()

在数组末尾添加元素,并返回数组长度。可传入参数列表。

let arr = [1,3]
let l = arr.push(5,6)
console.log(l);  // 4
console.log(arr); //  [1, 3, 5, 6]

如果想让数组2合并到数组1中,可以用到扩展运算符

let arr = [1,3]
let arr2 = [5,6]
arr.push(...arr2)
console.log(arr);  //[1, 3, 5, 6]

unshift()

在数组开头添加元素,并返回数组的新长度,传入的是参数列表。

let arr = [1,3]
let l = arr.unshift(0,2)
console.log(l);  //4
console.log(arr); // [0, 2, 1, 3]

pop()

删除数组最后一个元素,并返回该元素的值。没有参数

let arr = ['a','b','c']
arr.pop()  --> 'c'
arr  --> ['a','b']

如果在空数组上调用pop(),则返回undefined

如果不想改变原数组,则使用slice(0,-1)

shift()

删除数组第一个元素,并返回该元素的值。没有参数

let arr = ['a','b','c']
arr.shift()  -->'a'
arr --> ['b', 'c']

如果在空数组上调用pop(),则返回undefined

如果不想改变原数组,则使用slice(1)

splice()

在指定位置删除已存在的元素或者添加新的元素,并返回删除或添加的元素

语法:slice(start,deleteCount,item1,...itemn)

如果只传入一个参数,则从参数指定位置开始删除

let arr = ['a','b','c','d','e','f']

arr.splice(1)  --> ['b', 'c', 'd', 'e', 'f']
arr  --> ['a']

传入第二个参数,则是要删除的元素个数

arr.splice(1,3)  --> ['b', 'c', 'd']
arr  -->['a', 'e', 'f']

传入第三个参数列表,表示从start开始要加入数组中的元素

arr.splice(1,0,1,2)  
arr   -->['a', 1, 2, 'b', 'c', 'd', 'e', 'f']
//因为删除的个数为0,所以直接从start开始添加元素。
arr.splice(1,5,4)   -->[1, 2, 'b', 'c', 'd']
arr  -->['a', 4, 'e', 'f']

sort()

对数组进行排序,并返回新数组

默认排序是将元素转换为字符串,然后暗转它们的UTF-16码元值排序

参数可传入一个函数,且返回一个数字,如果数字大于0,则正序;小于0则逆序

let arr = [1,6,4,8,3]

arr.sort()  -->[1, 3, 4, 6, 8]
arr.sort((a,b)=>a-b)  -->[1, 3, 4, 6, 8]
arr.sort((a,b)=>b-a)  -->[8, 6, 4, 3, 1]

reverse()

反转数组中的元素,并返回已反转后的数组。

let arr = [1,6,4,8,3]

arr.reverse()  -->[3, 8, 4, 6, 1]
arr  -->[3, 8, 4, 6, 1]

fill()

语法:fill(value,start,end)

用value值取填充一个数组中从索引start到end内的全部元素,并返回修改后的数组

如果只传value,则全部填充

let arr = [2,10,4]

let newArr = arr.fill(1)
console.log(newArr);  //[1, 1, 1]
console.log(arr);  //[1, 1, 1]

如果传start,则从start开始,往后的所有元素都被填充

let arr = [2,10,4,4,2,0]

let newArr = arr.fill(1,3)
console.log(newArr);  //[2, 10, 4, 1, 1, 1]
newArr = arr.fill(0,2,5)
console.log(newArr);  //[2, 10, 0, 0, 0, 1]

copyWithin()

从数组的指定位置拷贝元素到数组的另一个指定位置去,并返回该数组

语法:copyWithin(target,start,end)

target为序列要开始替换的目标位置

start为复制的元素序列的起始位置,end为结束位置(左闭右开)

数组长度是不变的

let arr = [2,10,4,4,2,0]

arr.copyWithin(2)
console.log(arr);  //[2, 10, 2, 10, 4, 4]
//从索引为2开始,拷贝数组
arr.copyWithin(2,1)
console.log(arr);  //[2, 10, 10, 4, 4, 2]
arr.copyWithin(2,1,4)
console.log(arr); //[2, 10, 10, 4, 4, 0]
//从索引为2开始,拷贝索引1到4的

不改变原数组的方法

join()

join()方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串,用逗号或指定的分隔符字符串分隔。

如果省略参数,则默认用逗号分隔

如果数组元素有undefined或null,则此元素将被转换为空字符串

let arr = [1,2,undefined,3,null,4]

let newArr = arr.join()
let newArr2 = arr.join("")
let newArr3 = arr.join("-")

console.log(newArr);  // '1,2,,3,,4'
console.log(newArr2);  // '1234'
console.log(newArr3);  // '1-2--3--4'
console.log(arr);  // [1,2,undefined,3,null,4]  没有改变原数组

其内部使用的是toString()方法。

如果数组中嵌套数组,则不保留嵌套,如果数组中嵌套对象,则通过toString方法返回[object Object]

let arr = [[1,2],{id:1}]

let newArr = arr.join()

console.log(newArr);  // '1,2,[object Object]'

concat()

concat()方法用于合并两个或多个数组,将后面的数组合并到前面数组中,并返回一个新数组。

concat()可传入参数列表,如果省略参数,则concat返回调用此方法的原数组,则为浅拷贝

let arr = [1,,2]
let arr2 = [3,4,undefined]
let arr3 = [5,6]
let obj = {
    0:1,
    1:2,
    length:2
}

let newArr = arr.concat(arr2,arr3)
console.log(newArr);  // [1, empty, 2, 3, 4, undefined, 5, 6]
console.log(arr)  // [1, empty, 2]

当合并类数组时,默认情况下会将类数组当作对象合并,当Symbol.isConcatSpreadable设置为真值时才会将类数组看作数组。

let arr = [1,3]
let obj = {
    0:2,
    1:4,
    length:2
}
let obj2 = {
    0:6,
    1:7,
    length:2,
    [Symbol.isConcatSpreadable]:true
}

console.log(arr.concat(obj,obj2));  [1, 3, {0: 2, 1: 4, length: 2}, 6, 7]

slice()

语法:slice(start,end)

返回一个新的数组,相当于从原数组的start索引到end索引(左闭右开)的浅拷贝。切片

如果slice不传参数,或者传入0。则表示从索引0开始,全部拷贝

let arr = ['a','b','c']

arr.slice()  -->['a', 'b', 'c']
arr.slice(0)  -->['a', 'b', 'c']

如果只传入一个参数,则从当前参数的索引位开始,到最后

arr.slice(2)  -->['c']

如果参数为负数,则从末尾开始计算开始的索引位

arr.slice(-2)  -->['b', 'c']

indexOf、lastIndexOf

indexof()返回数组中第一次出现给定元素得下标,如果不存在则返回-1

lastIndexOf()返回数组中给定元素最后一次出现的索引,如果不存在则返回-1

let arr = ['a','f','g','w']

arr.indexOf('a')  --> 0
arr.indexOf('b')  -->-1

还可以传入第二个参数,第二个参数表示开始的索引位置

arr.indexOf('a',1)  --> -1
// 因为从索引位1开始,索引没有’a'

indexOf使用严格相等与之比较,所以传入NaN始终等于-1

let arr = ['a',NaN]

arr.indexOf(NaN)  --> -1

当数组位稀疏数组时,则跳过空槽

every()

测试一个数组内的所有元素是否都能通过指定函数的测试,并返回一个布尔值。ES6新增方法

语法:every(callbackFn,thisArg)

callbackFn为每个元素执行的函数,该函数调用时传入以下参数:

  • element/item:数组中当前正在处理的元素,必传
  • index:正在处理的元素在数组中的索引,选传
  • array:调用当前every方法的数组本身,选传

thisArg为执行callbackFn时用作this的值,选传

every()会遍历数组每一项,如果有一个不满足条件,则返回false,后面的元素不会再遍历。遍历完数组后,如果每一项都符合条件,则返回true

let arr = [1,2,3,4,5,6]
let e = arr.every(item=>{
    return item<3 
})
console.log(e);  //false

let e2 = arr.every(item=>{
    return item>0
})
console.log(e2)  //true

在稀疏数组上不会判断空值

let arr = [1,2,3,,4,5,6]
let e = arr.every((item,index,array)=>{
    return item !== undefined
})
console.log(e);   //true

如果想要修改原数组,可以利用callbackFn的第二个参数和第三个参数,手动修改原数组,但此方法本身是不改变原数组的。

let arr = [1,2,3,4,5,6]
let e = arr.every((item,index,array)=>{
    array[index] += 5
    return item<3
})
console.log(e);  //false
console.log(arr);  //[6, 7, 8, 4, 5, 6]

因为会遍历数组,如果当前元素不符合条件后会立马返回false,后面的元素都不会修改。

some()

测试数组中是否至少有一个元素通过指定函数的测试,并返回一个布尔值。用法和every差不多。 ES6新增方法

不同的是some()方法如果有一个元素符合条件,则返回true,且后面的元素不会再检测。遍历完数组后,如果没有一项符合条件,则返回false

let arr = [1,2,3,4,5,6]

let s = arr.some(item=>item>2)
console.log(s);  //true

let s2 = arr.some(item=>item>6)
console.log(s2);  //false

也可手动修改原数组。

filter()

遍历数组中的每一项,找到符合指定条件的元素返回,返回一个新数组。 ES6新增方法

也可以对数组进行浅拷贝。

let arr = [1,2,3,4,5,6]
let f = arr.filter(item=>item>3)
console.log(f);  // [4, 5, 6]
console.log(arr);  // [1, 2, 3, 4, 5, 6]

一般用来过滤数组内容,并且在稀疏数组上使用会跳过空槽

也可手动修改原数组

let arr = [1,2,3,4,5,6]
let f = arr.filter((item,index,array)=>{
    array[index] += 2
})
console.log(arr);  //[3, 4, 5, 6, 7, 8]

map()

map()方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次回调函数后的返回值组成。

用于映射数组

可对数组进行浅拷贝

let arr = [1,2,3,4,5,6]
let m = arr.map(item=>item*2)
console.log(m);  //[2, 4, 6, 8, 10, 12]
console.log(arr);  //[1, 2, 3, 4, 5, 6]

let m2 = arr.map(item=>item>2)
console.log(m2)  //[false, false, true, true, true, true]
//因为item>2 始终返回的是一个布尔值,而map产生的新数组是由每个元素调用回调函数的返回值组成

也可通过参数修改原数组。

forEach()

遍历数组,对数组的每个方法执行一次给定的函数,且没有返回值,返回结果为undefined

除非抛出异常,否则没有办法停止或中断forEach()循环

因为forEach内部用的while循环

let arr = [1,2,3,,4,5,6]
let f = arr.forEach(item=>{
    console.log(item);
})

image-20240813221528578

对于稀疏数组,为跳过空槽

find()、findLast()

find()方法返回数组中满足测试函数的第一个元素的值,否则返回undefined

findLast()方法反向迭代数组,并返回数组中满足测试函数的第一个元素的值,否则返回undefined

let arr = [2,10,4]
let f = arr.find(item=>item>3)
console.log(f);  //10
f = arr.find(item=>item>12)
console.log(f);  //undefined

f = arr.findLast(item=>item>3)
console.log(f);  //4

可通过调用回调函数修改原数组

findIndex()、findLastIndex()

findIndex()返回数组中满足测试函数的第一个元素的索引,若没找到则返回-1

findLastIndex()反向迭代数组,并返回数组中满足测试函数的第一个元素的索引,若没找到则返回-1

let arr = [2,10,4]
let f = arr.findIndex(item=>item>3)
console.log(f);  //1
f = arr.findLastIndex(item=>item>3)
console.log(f);  //2

可通过调用回调函数修改原数组

flat()

创建一个新的数组,并根据指定深度递归地将所有子数组元素拼接到新的数组中。

数组扁平化

默认深度为1

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

newArr = arr.flat(2)
console.log(newArr);  //[1, 2, 3, 4, 5]

newArr = arr.flat(4)
console.log(newArr);  //[1, 2, 3, 4, 5]

对于稀疏数组,会忽略空槽

如果深度超过数组深度,不会报错

可以对数组进行浅拷贝,但是需要自己设置深度


手写不用传入深度的数组扁平化的函数

function myFlat(arr){
    let newArr = []
    arr.forEach(element => {
        if(Array.isArray(element)){
            newArr.push(...myFlat(element))
        }else{
            newArr.push(element)
        }
    });
    return newArr
}

还可以利用reduce实现数组扁平化

flatMap()

对数组中的每个元素应用给定的回调函数,将结果展开一级,返回一个新数组

相当于先调用map()方法后再调用深度为1的flat方法

let arr = [1,2,3,[[4,5],6]]

let newArr = arr.flatMap(item=>item*2)
console.log(newArr);  //[2, 4, 6, NaN]
//因为数组扁平化的深度为1,而arr有深度为2,所以数组*2为NaN

reduce()

reduce() 方法对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

语法:reduce(callbackFn,init)

callbackFn可传入四个参数:

prev:表示上一次调用回调时的返回值,初始值为init或者arr[0]

item:表示正在处理的数组元素,在第一次调用时,如果有init,则为 arr[0] 的值,否则为 arr[1]。

index:表示正在处理的数组元素的索引,如果有init,则初始值为0,否则为1

array:调用reduce()的数组本身

let arr = [1,4,6,2,2]
//求数组项之和
let sum =  arr.reduce((prev,item)=>{
    return prev+item
})
console.log(sum);  //15

利用reduce实现数组扁平化

//利用reduce实现数组扁平化
function flatten(arr){
    //因为有初始值[],所以第一次调用prev为[]
    return arr.reduce((prev,item)=>{
        return prev.concat(Array.isArray(item) ? flatten(item) : item)
    },[])
}

includes()

用来判断一个数组是否包含一个指定的值,如果包含则返回true,否则返回false

let arr = [1,4,7,3,2]

let isInclude = arr.includes(2)
console.log(isInclude);  //true
isInclude = arr.includes(5)
console.log(isInclude);  //false

还可以传入第二个参数,表示开始搜索的索引,如果不传,则默认从0开始

let isInclude = arr.includes(4)
console.log(isInclude);  //true
isInclude = arr.includes(4,3)
console.log(isInclude);  //false

可以在稀疏数组中搜索到undefined