嘿,各位靓仔靓女们,今天咱们来聊聊JavaScript里两个神奇的“扁平化大师”——flat()
和 flatMap()
。 别担心,我保证用最通俗易懂的方式,把它们扒个底朝天,让你以后再也不怕那些嵌套的数组了!
一、flat()
: 数组的“夷为平地”神功
想象一下,你手里拿着一个俄罗斯套娃,一层套一层,打开起来贼麻烦。 flat()
函数的作用就类似于把这个套娃给拆了,把所有的小娃娃都放到一个平面上,这样你就可以一次性看到所有的小娃娃了!
1. 语法:
array.flat([depth])
array
: 不用说,就是你要扁平化的数组。depth
: (可选)指定扁平化的深度。 默认值是1
。Infinity
表示无限深度,也就是说,不管你的数组嵌套多少层,都能给你一次性扁平化到底!
2. 简单示例:
const arr1 = [1, 2, [3, 4]];
console.log(arr1.flat()); // 输出: [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
console.log(arr2.flat()); // 输出: [1, 2, 3, 4, [5, 6]] (默认深度为1,只扁平化一层)
console.log(arr2.flat(2)); // 输出: [1, 2, 3, 4, 5, 6] (指定深度为2,扁平化两层)
const arr3 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
console.log(arr3.flat(Infinity)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (无限深度,全部扁平化)
3. flat()
的一些小脾气:
-
跳过空位:
flat()
会自动跳过数组中的空位 (empty slots)。const arr4 = [1, 2, , 4, 5]; // 注意中间有一个空位 console.log(arr4.flat()); // 输出: [1, 2, 4, 5]
-
不改变原数组:
flat()
不会修改原始数组,而是返回一个新的扁平化后的数组。const arr5 = [1, [2, 3]]; const flattenedArr = arr5.flat(); console.log(arr5); // 输出: [1, [2, 3]] (原数组不变) console.log(flattenedArr); // 输出: [1, 2, 3]
4. flat()
的实际应用场景:
- 处理嵌套的数据结构: 比如从 API 返回的嵌套 JSON 数据,你需要把它们展开成一个平面数组进行处理。
- 简化复杂的数据操作: 有些算法需要处理扁平化的数据,使用
flat()
可以简化代码逻辑。
二、flatMap()
: “映射 + 扁平化” 的组合拳
flatMap()
就像一个武林高手,它不仅会“夷为平地”,还会先给你来一套“乾坤大挪移” (映射),然后再把结果扁平化。 简单来说,它相当于先执行 map()
,再执行 flat(1)
。
1. 语法:
array.flatMap(callback(currentValue[, index[, array]])[, thisArg])
callback
: 一个函数,用来处理数组中的每一个元素,并返回一个新的值(可以是数组)。currentValue
: 当前正在处理的元素的值。index
: (可选)当前元素的索引。array
: (可选)正在操作的数组。thisArg
: (可选)执行callback
函数时this
的值。
2. 简单示例:
const arr6 = [1, 2, 3];
const result1 = arr6.flatMap(x => [x * 2]);
console.log(result1); // 输出: [2, 4, 6] (相当于先 map 成 [[2], [4], [6]],再 flat(1) 成 [2, 4, 6])
const arr7 = ["it's Sunny in", "", "California"];
const result2 = arr7.flatMap(x => x.split(" "));
console.log(result2); // 输出: ["it's", "Sunny", "in", "", "California"] (先 split 成数组,再扁平化)
3. flatMap()
的一些特点:
-
始终只扁平化一层: 无论
callback
函数返回的数组嵌套多少层,flatMap()
都只会扁平化一层。const arr8 = [1, 2, 3]; const result3 = arr8.flatMap(x => [[x * 2]]); // callback 返回嵌套数组 console.log(result3); // 输出: [[2], [4], [6]] (只扁平化一层)
-
更简洁: 相比于先
map()
再flat()
,flatMap()
可以用一行代码完成相同的操作,代码更简洁易读。
4. flatMap()
的实际应用场景:
- 处理一对多的关系: 比如一个用户有多个订单,你可以用
flatMap()
把所有用户的订单提取到一个数组中。 -
过滤和转换数据: 你可以用
flatMap()
同时过滤掉一些元素,并对剩下的元素进行转换。const sentences = ["This is a sentence.", "Another one!"]; const words = sentences.flatMap(sentence => sentence.split(" ")) .filter(word => word.length > 0); // 过滤掉空字符串 console.log(words); // 输出: ["This", "is", "a", "sentence.", "Another", "one!"]
三、flat()
vs flatMap()
: 差异对比
为了让你更清楚地了解这两个函数的区别,我们用一个表格来总结一下:
特性 | flat() |
flatMap() |
---|---|---|
功能 | 将嵌套的数组扁平化。 | 先对数组中的每个元素执行 callback 函数(映射),然后将结果扁平化。 |
扁平化深度 | 可以指定扁平化的深度,默认为 1 ,可以设置为 Infinity 表示无限深度。 |
始终只扁平化一层。 |
是否需要 callback |
不需要。 | 需要,用于处理数组中的每个元素。 |
相当于 | 无。 | 相当于 array.map(callback).flat(1) 。 |
应用场景 | 处理嵌套的数据结构,简化复杂的数据操作。 | 处理一对多的关系,过滤和转换数据。 |
示例 | [1, [2, 3]].flat() => [1, 2, 3] |
[1, 2, 3].flatMap(x => [x * 2]) => [2, 4, 6] |
四、 兼容性问题
虽然 flat()
和 flatMap()
是 ES2019 (ES10) 引入的特性,但现在主流的浏览器都已经支持了它们。 不过,为了兼容一些老旧的浏览器,你可能需要使用 polyfill。 你可以使用 Babel 或者 Core-js 来添加 polyfill,这样即使在不支持 flat()
和 flatMap()
的浏览器上,你的代码也能正常运行。
五、 自己动手实现 flat()
和 flatMap()
为了更深入地理解 flat()
和 flatMap()
的原理,我们可以尝试自己动手实现它们。
1. 实现 flat()
:
function myFlat(arr, depth = 1) {
const result = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (Array.isArray(item) && depth > 0) {
// 如果是数组,并且深度大于0,则递归调用 myFlat()
result.push(...myFlat(item, depth - 1));
} else {
// 否则,直接将元素添加到结果数组中
result.push(item);
}
}
return result;
}
// 测试
const arr9 = [1, 2, [3, 4, [5, 6]]];
console.log(myFlat(arr9)); // 输出: [1, 2, 3, 4, [5, 6]]
console.log(myFlat(arr9, 2)); // 输出: [1, 2, 3, 4, 5, 6]
console.log(myFlat(arr9, Infinity)); // 输出: [1, 2, 3, 4, 5, 6]
2. 实现 flatMap()
:
function myFlatMap(arr, callback) {
const result = [];
for (let i = 0; i < arr.length; i++) {
const mappedValue = callback(arr[i], i, arr); // 执行 callback 函数
if (Array.isArray(mappedValue)) {
// 如果 callback 返回的是数组,则将数组中的元素添加到结果数组中
for (let j = 0; j < mappedValue.length; j++) {
result.push(mappedValue[j]);
}
} else {
// 否则,直接将 callback 返回的值添加到结果数组中
result.push(mappedValue);
}
}
return result;
}
// 测试
const arr10 = [1, 2, 3];
const result4 = myFlatMap(arr10, x => [x * 2]);
console.log(result4); // 输出: [2, 4, 6]
const arr11 = ["it's Sunny in", "", "California"];
const result5 = myFlatMap(arr11, x => x.split(" "));
console.log(result5); // 输出: ["it's", "Sunny", "in", "", "California"]
六、 总结
flat()
和 flatMap()
是 JavaScript 中非常实用的数组方法,可以帮助我们更方便地处理嵌套的数据结构。 flat()
专注于扁平化数组,而 flatMap()
则将映射和扁平化组合在一起,提供更强大的功能。 掌握了这两个函数,你就能够轻松应对各种复杂的数组操作了!
希望今天的讲座对你有所帮助。 记住,熟能生巧,多写代码,多实践,你也能成为数组处理的大师! 下次再见!