Iterator.prototype.flatMap()

Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.

Iterator 实例的 flatMap() 方法返回一个新的 迭代器助手,它获取原始迭代器中的每个元素,通过映射函数运行它,并生成映射函数返回的元素(包含在另一个迭代器或可迭代对象中)。

¥The flatMap() method of Iterator instances returns a new iterator helper that takes each element in the original iterator, runs it through a mapping function, and yields elements returned by the mapping function (which are contained in another iterator or iterable).

语法

¥Syntax

js
flatMap(callbackFn)

参数

¥Parameters

callbackFn

对迭代器生成的每个元素执行的函数。它应该返回一个迭代器或可迭代器,该迭代器或可迭代器产生要由 flatMap() 产生的元素,或者要产生的单个非迭代器/可迭代值。使用以下参数调用该函数:

element

数组中当前正在处理的元素。

index

数组中当前正在处理的元素的索引。

返回值

¥Return value

新的 迭代器助手。第一次调用迭代器助手的 next() 方法时,它会在底层迭代器生成的第一个元素上调用 callbackFn,并且返回值(应该是迭代器或可迭代对象)由迭代器助手逐一生成(例如 yield*)。当 callbackFn 返回的前一个元素完成时,将从底层迭代器中获取下一个元素。当底层迭代器完成时,迭代器助手也完成(next() 方法生成 { value: undefined, done: true })。

¥A new iterator helper. The first time the iterator helper's next() method is called, it calls callbackFn on the first element produced by the underlying iterator, and the return value, which should be an iterator or iterable, is yielded one-by-one by the iterator helper (like yield*). The next element is fetched from the underlying iterator when the previous one returned by callbackFn is completed. When the underlying iterator is completed, the iterator helper is also completed (the next() method produces { value: undefined, done: true }).

例外情况

¥Exceptions

TypeError

如果 callbackFn 返回非迭代器/可迭代值或字符串基元,则抛出此异常。

描述

¥Description

flatMap 接受 callbackFn 的两种返回值:迭代器或可迭代对象。它们的处理方式与 Iterator.from() 相同:如果返回值是可迭代的,则调用 @@iterator 方法并使用返回值;否则,返回值被视为迭代器并调用其 next() 方法。

¥flatMap accepts two kinds of return values from callbackFn: an iterator or iterable. They are handled in the same way as Iterator.from(): if the return value is iterable, the @@iterator method is called and the return value is used; otherwise, the return value is treated as an iterator and its next() method is called.

js
[1, 2, 3]
  .values()
  .flatMap((x) => {
    let itDone = false;
    const it = {
      next() {
        if (itDone) {
          return { value: undefined, done: true };
        }
        itDone = true;
        return { value: x, done: false };
      },
    };
    switch (x) {
      case 1:
        // An iterable that's not an iterator
        return { [Symbol.iterator]: () => it };
      case 2:
        // An iterator that's not an iterable
        return it;
      case 3:
        // An iterable iterator is treated as an iterable
        return {
          ...it,
          [Symbol.iterator]() {
            console.log("@@iterator called");
            return it;
          },
        };
    }
  })
  .toArray();
// Logs "@@iterator called"
// Returns [1, 2, 3]

示例

¥Examples

合并映射

¥Merging maps

以下示例将两个 Map 对象合并为一个:

¥The following example merges two Map objects into one:

js
const map1 = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3],
]);
const map2 = new Map([
  ["d", 4],
  ["e", 5],
  ["f", 6],
]);

const merged = new Map([map1, map2].values().flatMap((x) => x));
console.log(merged.get("a")); // 1
console.log(merged.get("e")); // 5

这可以避免创建地图内容的任何临时副本。请注意,数组 [map1, map2] 必须首先转换为迭代器(使用 Array.prototype.values()),因为 Array.prototype.flatMap() 只展平数组,而不展平可迭代对象。

¥This avoids creating any temporary copies of the map's content. Note that the array [map1, map2] must first be converted to an iterator (using Array.prototype.values()), because Array.prototype.flatMap() only flattens arrays, not iterables.

js
new Map([map1, map2].flatMap((x) => x)); // Map(1) {undefined => undefined}

返回字符串

¥Returning strings

字符串是可迭代的,但 flatMap() 明确拒绝从 callbackFn 返回的字符串基元,这是因为按代码点迭代的行为通常不是你想要的。

¥Strings are iterable, but flatMap() specifically rejects string primitives returned from callbackFn, this is because the behavior of iterating by code points is often not what you want.

js
[1, 2, 3]
  .values()
  .flatMap((x) => String(x))
  .toArray(); // TypeError: Iterator.prototype.flatMap called on non-object

你可能希望将其封装在一个数组中,以便将整个字符串生成为一个:

¥You may want to wrap it in an array instead so the entire string is yielded as one:

js
[1, 2, 3]
  .values()
  .flatMap((x) => [String(x)])
  .toArray(); // ['1', '2', '3']

或者,如果想要按代码点迭代的行为,你可以使用 Iterator.from() 将其转换为正确的迭代器:

¥Or, if the behavior of iterating by code points is intended, you can use Iterator.from() to convert it to a proper iterator:

js
[1, 2, 3]
  .values()
  .flatMap((x) => Iterator.from(String(x * 10)))
  .toArray();
// ['1', '0', '2', '0', '3', '0']

规范

Specification
Iterator Helpers
# sec-iteratorprototype.flatmap

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看