Array.prototype.flatMap
// Array.prototype.flatMap ES2020
const arr = ['123', '456', '678'];
// 使用 map 和 flat 方法实现平铺
const newArr1 = arr
.map(function (item) {
return item.split('');
})
.flat();
console.log(newArr1);
等同于
将 map
和 flat
结合使用,实际上可以通过 flatMap
一步完成。这种方式的效率更高,因为它避免了对数组的多次遍历。ECMA-262
和 MDN
都有提到这种性能差异。
const newArr2 = arr.flatMap(function (item) {
return item.split('');
});
console.log(newArr2);
参数
flatMap
接受一个回调函数和一个可选的 this
指向作为参数。
// 参数说明:
// 1. 当前遍历的元素
// 2. 当前遍历的元素在数组中的索引
// 3. 数组本身
// flatMap 的第二个参数可以修改回调函数的 `this` 指向
const arr = ['123', '456', '678'];
const newArr3 = arr.flatMap(
function (item, index, arr) {
console.log(item, index, arr);
console.log(this); // 显示 `this` 的值
},
{ a: 1 }
);
在上述代码中,this
被绑定为 { a: 1 }
,回调函数中 this
的值会被输出。
应用场景
拆解英文句子
如果你需要将英文句子按单词进行拆分,可以使用 flatMap
,它将每个句子按空格拆分为单个单词,并将其平铺到一个数组中。
const arr = ["My name's SMC", "I'm 35", 'years old.'];
const newArr = arr.flatMap(function (item) {
return item.split(' '); // 使用空格拆分每个句子
});
console.log(newArr);
// ['My', "name's", 'SMC', "I'm", '35', 'years', 'old.']
遍历时增加项
在处理数组时,如果你希望对负数进行特殊处理,可以通过 flatMap
在遍历时增加额外的项。比如,将负数与前一个元素相加。
const arr = [1, -2, -3, 5, 8, -9, 6, 7, 0];
const newArr = arr.flatMap(function (item, index) {
if (item < 0 && index >= 1) {
return [item, `${item} + ${arr[index - 1]} = ${item + arr[index - 1]}`];
}
return item;
});
console.log(newArr);
// [1, -2, '-2+1 = -1', -3, '-3+-2 = -5', 5, 8, -9, '-9+8 = -1', 6, 7, 0]
在这个例子中,负数会与前一个数字相加,并以字符串的形式返回。
flatMap
方法实现
如果你希望自己实现类似 flatMap
的功能,可以按照以下步骤:
const arr = ['123', '456', '678'];
Array.prototype.myFlatMap = function (cb) {
// 判断回调函数是否有效
if (typeof cb !== 'function') {
throw new TypeError('Callback must be a function');
}
// 保存当前数组和传入的 this 值
var arr = this,
arg2 = arguments[1],
res = [],
item;
for (var i = 0; i < arr.length; i++) {
// 回调函数会使用 apply 方法绑定 this
item = cb.apply(arg2, [arr[i], i, arr]);
// 如果返回值为真,加入结果数组
if (item) {
res.push(item);
}
}
// 使用 flat 方法进行数组平铺
return res.flat();
};
const newArr = arr.myFlatMap(function (item) {
return item.split(''); // 将每个字符串拆分为字符数组
});
console.log(newArr);