JavaScript 数组高阶函数 | 青训营笔记

89 阅读6分钟

这是我参与「第四届青训营」笔记创作活动的的第 2 天

在 JavaScript 中有许多可以供我们方便地操作、遍历数组的函数/高阶函数,熟练地使用这些函数可以使得我们的代码更简洁,更具可读性。本文列举了一些比较常用的 JavaScript 数组操作函数以及用法。

数组高阶函数

every/some

用于判断一个数组中的所有元素是否符合某个条件。

下面是使用 every 函数判断数组中的数是否全部是偶数的示例:

const arr1 = [1, 2, 3]
const arr2 = [2, 4, 6]
const isEven = e => e % 2 == 0
arr1.every(isEven) // false
arr2.every(isEven) // true

every 还有一个姐妹函数:some 。这个函数只需有一个元素符合给定条件时就返回 true,而 every 是仅当所有元素符合条件时才返回 true

filter

返回一个新的数组,包含原数组中符合某条件的所有元素。

下面是使用 filter 函数筛选数组中所有奇数的示例:

const arr = [1, 2, 3]
const isOdd = e => e % 2 != 0
arr.filter(isOdd) // [1, 3]

其中传入的 callback 函数除了会传递元素本身外,第二个参数还会传递元素的索引,第三个参数传递数组本身。

find/findIndex/findLast/findLastIndex

用于找到数组中符合某条件的第一个元素,如果找不到则返回 undefined

下面是使用 find 函数寻找数组中第一个偶数的示例:

const arr = [1, 2, 3, 4, 5]
const isEven = e => e % 2 == 0
arr.find(isEven) // 2

find 高阶函数还有一些姐妹函数,如:findIndex 用于找到第一个符合条件的元素索引,如果没有符合条件的元素则返回 -1;findLast 用于从末尾开始寻找符合条件的元素;findLastIndex 从末尾开始寻找,但是也是返回元素的索引。

includes

如果你写出了类似 arr.find(element) != -1 之类的代码,那么说明你的需求只是想要判断一个元素知否在数组中存在,那么这种时候可以使用 includes 函数,虽然与上面的代码没有什么区别,但是语义更加清晰,代码的可读性更加强。

const arr = [1, 2, 3]
arr.includes(3) // true
arr.includes(7) // false

forEach

用于遍历数组,与增强 for 循环类似,但是 forEach 循环不能退出,只能通过抛出异常的方式退出循环,个人认为这种方式退出循环十分不优雅,如果有退出循环的需求建议还是使用增强 for 循环来遍历数组。

const arr = [1, 2, 3]
arr.forEach(e => console.log(e))
// 1
// 2
// 3

map

创建一个新的数组,新数组中的每一个元素由原数组中的元素映射(map)而来。

下面是使用 map 函数将一个数组中的所有元素值乘以 2 的示例:

const arr = [1, 2, 3]
arr.map(e => e * 2) // [2, 4, 6]

flat/flatMap

flat 函数会按照指定的深度打平一个数组。

也就是遍历数组,并会递归到一定的深度,将遍历到的所有元素抽取出来作为一个一维数组。

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

flatMap 函数其实看名字也就知道了,这个函数是 flatmap 两个函数的亲戚~

使用 flatMap 相当于同时使用 mapflat,将所有的元素先给 map 进行一次映射,然后将映射的结果打平。

const arr = [1, 2, 3, 4]
arr.map(e => [e * 2]) // [[2], [4], [6], [8]]
arr.flatMap(e => [e * 2]) // [2, 4, 6, 8]

reduce/reduceRight

这两个函数与 forEach 类似,但是会维护一个计算结果值,作为 callback 函数的第一个参数。

callback 函数的返回值将作为下一次循环的计算结果,如果是第一次循环,这个结果的值则为 0。

下面是一个使用 reduce 函数计算数组所有元素和的示例:

const arr = [1, 2, 3]
arr.reduce((result, cur) => result + cur) // 6

reduceRight 函数与 reduce 函数基本一致,不同点在于 reduceRight 函数是从数组的末尾开始遍历,因此在求和场景下使用这两个函数并没有什么区别。

其他数组函数

增删元素

直接增加/删除元素的方法一共有四种:pushpopunshiftshift。其中 pushunshift 用于添加元素,popshift 用于移除元素。

  • push:向末尾添加一个元素
  • pop:移除末尾的元素
  • unshift:向开头添加一个元素
  • shift:移除开头的元素

其中添加元素的函数会返回添加之后的数组长度,而移除元素的方法则会返回被移除的元素本身。

concat

合并两个数组,返回一个新数组。

const arr1 = [1, 2, 3]
const arr2 = [4, 5]
arr1.concat(arr2) // [1, 2, 3, 4, 5]

fill

使用一个值填充数组,也可以指定填充的范围。

const arr = [1, 2, 3]
arr.fill(4) // [4, 4, 4]

填充指定索引范围内的所有元素。如果不提供第二个索引,则默认填充第一个索引到末尾的所有元素。

const arr = [1, 2, 3]
arr.fill(6, 0, 1) // [6, 2, 3]
const arr = [1, 2, 3]
arr.fill(5, 1) // [1, 5, 5]

reverse

将数组倒序,需要注意的是这个方法不是返回一个新的数组,而是在原来的数组上进行操作。

const arr = [1, 2, 3]
arr.reverse() // [3, 2, 1]

sort

对数组进行排序,可以传入一个比较函数来自定义排序规则。

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

需要注意的是如果不传入一个比较函数,那么会默认按照 Unicode 顺序来进行排序,即使你的数组是一个纯数字的数组。

slice

获取数组中指定索引范围内元素的浅拷贝。

const arr = [1, 2, 3, 4, 5]
arr.slice(2, 4) // [3, 4]

如果不指定第二个索引,那么默认是浅拷贝第一个索引到数组末尾的所有元素。

splice

这个函数虽然与上面的 slice 长得很像,但是做的事情却完全不一样。

使用这个函数可以快速地在数组的一个位置删除元素并添加新的元素。

第一个参数是开始删除元素的索引,第二个参数是删除的元素个数,如果不提供则删除从索引开始后面的所有元素。后续的所有参数则是要添加到删除位置的新元素。

const arr = [1, 2, 3, 4, 5]
arr.splice(3) // [4, 5]
arr // [1, 2, 3]
const arr = [1, 2, 3, 4, 5]
arr.splice(2, 2) // [3, 4]
arr // [1, 2, 5]
const arr = [1, 2, 3, 4, 5]
arr.splice(2, 2, 7, 8, 9) // [3, 4]
arr // [1, 2, 7, 8, 9, 5]

join

join 方法用于将数组的所有元素用一个字符串拼接起来。

const arr = [1, 2, 3, 4, 5]
arr.join('-') // '1-2-3-4-5'

参考

  1. mdn web docs