Array.prototype.flatMap()
flatMap() 方法 Array 例項返回一個新陣列,該陣列是透過將給定的回撥函式應用於陣列的每個元素,然後將結果扁平化一級而形成的。它與 map() 後跟一個深度為 1 的 flat()(arr.map(...args).flat())完全相同,但比單獨呼叫這兩個方法效率稍高。
試一試
const arr = [1, 2, 1];
const result = arr.flatMap((num) => (num === 2 ? [2, 2] : 1));
console.log(result);
// Expected output: Array [1, 2, 2, 1]
語法
flatMap(callbackFn)
flatMap(callbackFn, thisArg)
引數
callbackFn-
為陣列中的每個元素執行的函式。它應該返回一個包含新陣列新元素的陣列,或者一個要新增到新陣列中的單個非陣列值。該函式使用以下引數呼叫
thisArg可選-
在執行
callbackFn時用作this的值。請參閱 迭代方法。
返回值
一個新陣列,其中每個元素都是回撥函式的計算結果,並扁平化一級。
描述
flatMap() 方法是 迭代方法。有關回調函式的詳細說明,請參閱 Array.prototype.map()。flatMap() 方法與 map(callbackFn, thisArg) 後跟 flat(1) 完全相同 — 對於每個元素,它會生成一個包含新元素的新陣列,並將這些生成的陣列連線起來形成一個新陣列。有關這些方法如何工作的更多資訊,請閱讀 迭代方法 部分。
flatMap() 方法是 泛型。它只期望 this 值具有 length 屬性和整數鍵屬性。但是,從 callbackFn 返回的值如果是要扁平化的,則必須是陣列。
替代方案
預先分配並顯式迭代
const arr = [1, 2, 3, 4];
arr.flatMap((x) => [x, x * 2]);
// is equivalent to
const n = arr.length;
const acc = new Array(n * 2);
for (let i = 0; i < n; i++) {
const x = arr[i];
acc[i * 2] = x;
acc[i * 2 + 1] = x * 2;
}
// [1, 2, 2, 4, 3, 6, 4, 8]
請注意,在這種特定情況下,flatMap 方法比 for 迴圈方法慢 — 這是因為建立了必須進行垃圾回收的臨時陣列,並且返回的陣列不需要頻繁調整大小。但是,在需要其靈活性和可讀性的情況下,flatMap 仍然是正確的解決方案。
示例
map() 和 flatMap()
const arr = [1, 2, 3, 4];
arr.map((x) => [x * 2]);
// [[2], [4], [6], [8]]
arr.flatMap((x) => [x * 2]);
// [2, 4, 6, 8]
// only one level is flattened
arr.flatMap((x) => [[x * 2]]);
// [[2], [4], [6], [8]]
雖然上面的例子可以用 map 來實現,但這裡有一個更好地展示 flatMap() 用法的示例。
讓我們從句子列表中生成一個單詞列表。
const arr = ["it's Sunny in", "", "California"];
arr.map((x) => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]
arr.flatMap((x) => x.split(" "));
// ["it's","Sunny","in", "", "California"]
請注意,輸出列表的長度可能與輸入列表的長度不同。
在 map() 中新增和刪除專案
flatMap 可用作在 map 過程中新增和刪除專案(修改專案數量)的方法。換句話說,它允許你將多個專案對映到多個專案(透過單獨處理每個輸入項),而不是始終一對一。從這個意義上說,它的作用與 filter 相反。返回一個包含 1 個元素的陣列以保留該項,返回一個包含多個元素的陣列以新增項,或者返回一個包含 0 個元素的陣列以刪除該項。
// Let's say we want to remove all the negative numbers
// and split the odd numbers into an even number and a 1
const a = [5, 4, -3, 20, 17, -33, -4, 18];
// |\ \ x | | \ x x |
// [4,1, 4, 20, 16, 1, 18]
const result = a.flatMap((n) => {
if (n < 0) {
return [];
}
return n % 2 === 0 ? [n] : [n - 1, 1];
});
console.log(result); // [4, 1, 4, 20, 16, 1, 18]
使用 callbackFn 的第三個引數
如果想訪問陣列中的另一個元素,array 引數就很有用,尤其是在沒有引用該陣列的現有變數時。以下示例首先使用 filter() 提取操作站,然後使用 flatMap() 建立一個新陣列,其中每個元素包含一個站點及其下一個站點。對於最後一個站點,它返回一個空陣列以將其從最終陣列中排除。
const stations = ["New Haven", "West Haven", "Milford (closed)", "Stratford"];
const line = stations
.filter((name) => !name.endsWith("(closed)"))
.flatMap((name, idx, arr) => {
// Without the arr argument, there's no way to easily access the
// intermediate array without saving it to a variable.
if (idx === arr.length - 1) return []; // last station has no next station
return [`${name} - ${arr[idx + 1]}`];
});
console.log(line); // ['New Haven - West Haven', 'West Haven - Stratford']
array 引數不是正在構建的陣列——無法從回撥函式訪問正在構建的陣列。
在稀疏陣列上使用 flatMap()
由於 map() 不會呼叫回撥函式,因此 callbackFn 不會被呼叫來處理源陣列中的空槽,而 flat() 會忽略返回陣列中的空槽。
console.log([1, 2, , 4, 5].flatMap((x) => [x, x * 2])); // [1, 2, 2, 4, 4, 8, 5, 10]
console.log([1, 2, 3, 4].flatMap((x) => [, x * 2])); // [2, 4, 6, 8]
在非陣列物件上呼叫 flatMap()
flatMap() 方法讀取 this 的 length 屬性,然後訪問鍵為小於 length 的非負整數的每個屬性。如果回撥函式的返回值不是陣列,它總是直接附加到結果陣列中。
const arrayLike = {
length: 3,
0: 1,
1: 2,
2: 3,
3: 4, // ignored by flatMap() since length is 3
};
console.log(Array.prototype.flatMap.call(arrayLike, (x) => [x, x * 2]));
// [1, 2, 2, 4, 3, 6]
// Array-like objects returned from the callback won't be flattened
console.log(
Array.prototype.flatMap.call(arrayLike, (x) => ({
length: 1,
0: x,
})),
);
// [ { '0': 1, length: 1 }, { '0': 2, length: 1 }, { '0': 3, length: 1 } ]
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-array.prototype.flatmap |
瀏覽器相容性
載入中…