JavaScript中操作数组的方法

81 阅读5分钟

数组是一种常见的数据结构,开发者经常需要对数组进行各种各样的处理,本文就来聊聊JavaScript中常见的数组操作方法。

forEach

forEach方法中,数组的每一个元素都会执行callbackFn。

const array = [1, 2, 3];
array.forEach((element, index, arr) => {
  console.log(element); // 1, 2, 3
  console.log(index); // 0, 1, 2
  console.log(arr); // [1, 2, 3]
})

forEach会跳过数组中的空位。

const array = [1, 2, , 3];
array.forEach((element, index, arr) => {
  console.log("el", element); // 1, 2, 3 跳过为空的索引和值
  console.log("i", index); // 0, 1, 3 
  console.log(arr); // [1, 2, empty, 3]
})

forEach永远返回undefined,且不可链式调用,这也是它与map()的区别。

需要注意的是,没有办法中止或跳出forEach循环,如果需要中止或跳出循环可以使用for infor of

map

map方法将数组中每一个元素执行callbackFn后的结果组合起来形成一个新数组,但并不会修改原始数组,因此如果不使用返回的新数组的话建议不要使用map方法,或许forEach更合适一点。

const arr = [1, 2, 3, 4, 5]
const newArr = arr.map(item => item * item)
console.log(arr) // [1, 2, 3, 4, 5]
console.log(newArr) // [1, 4, 9, 16, 25]

reduce

reduce方法对数组中的每一个元素执行callbackFn,该方法传入四个参数:

previousValue:上一次计算返回的值,如果是第一次计算,当指定初始值时即是初始值initialValue,否则为数组索引为0的元素;

currentValue:当前正在处理的元素,在第一次调用时,如果传入了initialValue,则为数组索引为0的元素,否则为数组索引为1的元素;

currentIndex:数组中正在处理的元素的索引,在第一次调用时,如果传入了initialValue,则从0开始,否则从1开始;

array:用于遍历的数组。

reduce方法不会改变原始数组,汇总计算结果返回单个新的值

const arr = [1, 2, 3, 4, 5]
const sum = arr.reduce((prev, current) => {
  return prev + current;
}, 1)
// 16
console.log(sum)

可以借助reduce方法对数组去重

const arr = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
const newArr = arr.reduce((prev, current) => {
  if (!prev.includes(current)) {
    prev.push(current)
  }
  return prev
}, [])
// [1, 2, 3, 4, 5, 6]
console.log(newArr)

filter

filter方法对数组中的每一个元素执行callbackFn,返回一个通过callbackFn的所有元素的新数组,该方法不会修改原始数组。

const arr = [2, 5, 7, 9, 10, 25, 18]
// 输出大于 10 的元素
const newArr = arr.filter((item) => item > 10)
console.log(newArr) //  [25, 18]

concat

concat 方法连接两个或多个数组,并返回一个新数组,不改变原始数组,可以实现对数组的浅拷贝

[1, 2, 3].concat([4, 5, 6]) // [1, 2, 3, 4, 5, 6]
[1, 2, 3].concat([4, 5, 6], [7, 8, 9]) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

ES6中的扩展运算符同样可实现上述功能,并且也对数组进行浅拷贝

[...[1, 2, 3], ...[4, 5, 6]] // [1, 2, 3, 4, 5, 6]

some、every

some

some方法对数组中的每一个元素执行callbackFn,它可以检测数组中是否至少有一个元素通过了callbackFn函数测试,如果找到了这个值,则立刻返回true。

[1, 2, 3, 4, 5].some((item) => item > 10) // false
[1, 2, 3, 4, 5].some((item) => item > 3) // true

every

every方法与some方法基本类似,不同的是,只有在数组中所有元素都通过callbackFn函数测试时才会返回true,否则返回false。

[1, 2, 3, 4, 5].some((item) => item < 10) // true
[1, 2, 3, 4, 5].some((item) => item > 3) // false

copyWithin

copyWithin是ES6提供的方法,它将数组中指定元素浅拷贝到该数组指定位置,会覆盖原本的元素,并将这个数组返回,不会改变数组的长度。 它接收三个参数:

target:从该位置开始拷贝数据,如果为负数,则从末尾开始计数,如果大于arr.length,则不发生拷贝;

start:从该位置开始读取数据,默认为0;

end:到该位置停止读取数据,默认为arr.length

[1, 2, 2, 5, 7, 10].copyWithin(2, 4, 5) // [1, 2, 7, 5, 7, 10]
[1, 2, 3, 4, 5].copyWithin(-2) // [1, 2, 3, 1, 2]

find、findIndex

find 和 findIndex 是ES6提供的方法,分别用于查询数组中满足条件的元素和满足条件元素的索引。

find

find方法返回满足条件的第一个元素的值,否则返回undefined。该方法不会改变原始数组。

[1, 2, 3, 4, 5, 6].find((item) => item > 3) // 4

findIndex

findIndex方法返回满足条件的第一个元素的索引,若没有满足条件的元素,则返回-1。

[1, 2, 3, 4, 5, 6].find((item) => item > 3) // 3
[1, 2, 3, 4, 5, 6].find((item) => item > 10) // -1

flat、flatMap

flat 和 flatMap 是ES6提供的方法,通过递归遍历的方式,对多维数组进行扁平化,并返回扁平化后的数组。

flat

flat接收一个深度的参数,指定要扁平化到哪一维度,默认为1

[1, 2, [3, 4, [5, 6]]].flat() // [1, 2, 3, 4, [5, 6]]
[1, 2, [3, 4, [5, 6]]].flat(2) // [1, 2, 3, 4, 5, 6]

flat会移除数组中的空位

[1, 2, , 3, 4].flat() // [1, 2, 3, 4]

可以使用reduce + concat实现二维数组的扁平化

const arr = [1, 2, [3, 4]]
arr.reduce((prev, current) => prev.concat(current), [])

使用递归遍历扁平化无限多层的数组

const arr = [1, 2, [3, 4, [5, 6]]]
function flatten (arr, depth) {
  if (depth < 0) return arr.slice()
  return arr.reduce((prev, current) => prev.concat(Array.isArray(current) ? flatten(current, depth - 1) : current), [])
}
flatten(arr, Infinity) // [1, 2, 3, 4, 5, 6]

flatMap

flatMap对原数组的每个成员执行一个callbakFn,这个callbackFn相当于map方法,将返回的结果再执行一遍flat()方法。该方法返回一个新数组,不改变原数组。且该方法只能展开一层数组。

[1, 2, 3, [4, 5]].flatMap((item) => item) // [1, 2, 3, 4, 5]
[1, 2, 3, 4].flatMap((item) => [item * 2]) // [2, 4, 6, 8]
// 只能展开一层
[1, 2, 3, 4].flatMap((item) => [[item * 2]]) // [[2], [4], [6], [8]]

entries、keys、values

它们都是ES6提供的方法,都返回一个array的迭代器对象,entries返回键值对的迭代器对象,keys返回键的迭代器对象,values返回值的迭代器对象

const arr = [1, 2, 3, 4, 5]
const valIterator = arr.values()
const keyIterator = arr.keys()
const enIterator = arr.entries()
// next() 返回一个对象,done 代表迭代器是否结束,结束为true,否则为false,value是一个键值对的数组
enIterator.next(); // {value: [0, 1], done: false}