ES6 中的数组拓展方法 flat() & flatMap()

之前有使用过 flat() 方法,但是一直不知道 flatMap() 方法,在使用 map() 方法组装集合的时候,在组装完成之后还要链式调用一下 flat(),如果可以知道 flatMap() 代码还能精简一点,也方便递归返回的数组内容。

本来是上个月发现的,但隔了一个月才有时间写,已经想不起来当时怎么发现的 flatMap() 这个方法了…
就直接跳过前置场景,直接开始聊这两个扩展方法吧。

Array.prototype.flat([depth])

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回,对原数据没有影响。

flat() 默认深度为 1,如果想要 “拉平” 多层的嵌套数组,可以将 flat() 方法的参数写成一个整数,表示想要拉平的层数。
✨ 如果不管有多少层嵌套,都要转成一维数组,可以用 Infinity 关键字作为参数。
✨ 如果原数组有空位,flat()方法会跳过空位(过滤掉空值)

var arr1 = [1, 2, [3, 4]];
// 展开一层数组
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

// 展开两层数组
arr2.flat(2);
// [1, 2, 3, 4, 5, 6]

// 使用 Infinity,可展开任意深度的嵌套数组
var arr3 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// flat() 方法会移除数组中的空项
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]

很容易理解的一个方法,就是推平数组,其实成为自己想要的一维数组。不过可以接收一个 depth 参数,我是再写这篇笔记的时候才知道的,所以还是要多记笔记啊。


Array.prototype.flatMap(callback [, thisArg]))

flatMap() 方法对原数组的每个成员执行一个函数(相当于执行 Array.prototype.map()),然后对返回值组成的数组执行 flat() 方法。该方法返回一个新数组,不改变原数组。

这个方法如果在知道 flat() 方法之后直接看,就还挺清楚作用是什么的,但是一看MDN上的说明,瞬间就被迷糊了….
其实简单来说是先 map() 然后执行 flat() 的简化版(不能指定深度)。

flatMap() 只能展开一层数组

let arr = ["it's Sunny in", "", "California"];

arr.map(x => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]

arr.map(x => x.split(" ")).flat()
// ["it's","Sunny","in", "", "California"]

arr.flatMap(x => x.split(" "));
// ["it's","Sunny","in", "", "California"]

尾声

使用 reduce()concat() 来替代 flat() 方法就不复述了,直接去看MDN上的实现就好。

是不是发现了一个 Infinity 关键字?这个关键字可以在哪些地方使用?

Infinity 是一个全局变量(只读),大于任何值,你也可以取反 -Infinity 使用
基本上只要可以传入一个正整数来 比较 或者 迭代 的都可以使用它

📚 资源

Array.prototype.flat() - JavaScript | MDN
Array.prototype.flatMap() - JavaScript | MDN
§ 9.数组实例的 flat(),flatMap() - 数组的扩展 - ECMAScript 6入门
Infinity - JavaScript | MDN