Spec-Zone.ru › JavaScript

Iterator.concat()

Базовая версия Недавно доступно

Эта функция работает на последних устройствах и версиях браузеров. Эта функция может не работать на старых устройствах или версиях браузеров. Она доступна во всех браузерах с марта 2026 года.

Статический метод Iterator.concat() создает новый объект Iterator из списка итерируемых объектов. Новый итератор выдает значения из каждого входного итерируемого объекта последовательно.

Синтаксис

Iterator.concat(it)
Iterator.concat(it1, it2)
Iterator.concat(it1, it2, /* …, */ itN)

Параметры

it1, it2, …, itN
Объект, реализующий протокол итерируемости. Итераторы, которые также не являются итерируемыми, не могут быть переданы напрямую этому методу; они должны быть предварительно обернуты с помощью Iterator.from().

Возвращаемое значение

Новый объект Iterator, который выдает значения из каждого входного итерируемого объекта последовательно.

Описание

Метод Iterator.concat() концептуально похож на метод concat() в Array, но он работает с любым типом итерируемого объекта и возвращает итератор вместо массива. Это означает, что итерируемые объекты могут быть итерированы лениво, избегая ненужного выделения памяти или вычислений. Это также означает, что, технически, вы можете конкатенировать бесконечные итерируемые объекты, но результаты от итерируемых объектов после первого бесконечного итерируемого объекта никогда не будут достигнуты.

Хотя каждый итерируемый объект может быть бесконечным, список итерируемых объектов должен быть конечным — и довольно ограниченным по количеству, потому что движки накладывают очень низкое ограничение на количество аргументов функции. Если вам нужно конкатенировать большое (даже бесконечное) количество итерируемых объектов, используйте вместо этого Iterator.prototype.flatMap().

function* infiniteIterables() {
  for (let i = 1; ; i++) {
    yield Array(i).fill(i);
  }
}

// BAD:
// Iterator.concat(...infiniteIterables());
// The spread operator never finishes

// GOOD:
const it = infiniteIterables().flatMap((x) => x);
// Infinite sequence of numbers: 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ...

Метод Iterator.concat() схож по функциональности со следующей функцией, которая использует оператор yield* для выдачи значений из каждого входного итерируемого объекта последовательно:

function* concat(...iterables) {
  for (const iterable of iterables) {
    yield* iterable;
  }
}

Как и yield*, Iterator.concat() не поддерживает аргументы, которые не являются итерируемыми (т. е. не имеют метода [Symbol.iterator]()). Это связано с тем, что Iterator.concat() всегда берет на себя управление своими итераторами и закрывает открытые итераторы при выходе из метода. С итерируемыми аргументами Iterator.concat() получает итераторы по одному и просто закрывает текущий итератор, когда итерация останавливается. В случае с аргументами-итераторами неясно, кто — вызывающий код или Iterator.concat() — должен отвечать за закрытие итераторов, особенно тех, до которых Iterator.concat() еще не дошел, поэтому метод просто запрещает неитерируемые аргументы.

Примеры

Объединение карт

В этом примере мы создаем новый Map, который является объединением трех других карт. Конструктор Map() принимает итерируемый объект пар ключ-значение, в то время как итератор Map выдает пары ключ-значение из карты, поэтому достаточно просто использовать Iterator.concat() для карт, чтобы создать новую карту.

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

const map = new Map(Iterator.concat(map1, map2, map3));
console.log(map);
// Map(5) {'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 6}

Обратите внимание, что значение ключа "a" в результирующей карте — 5. Это потому, что конструктор Map использует последнее значение для каждого ключа.

Конкатенация бесконечных итерируемых объектов

Когда любой из входных итерируемых объектов бесконечен, результирующий итератор также будет бесконечным. Это не является немедленной проблемой, поскольку итераторы могут быть потреблены лениво и закрыты в любое время, но это означает, что итерируемые объекты после первого бесконечного итерируемого объекта никогда не будут достигнуты.

function* it1() {
  yield 1;
  yield 2;
}

function* it2() {
  let i = 3;
  while (true) {
    yield i++;
  }
}

function* it3() {
  yield "done";
}

const it = Iterator.concat(it1(), it2(), it3());
for (const value of it.take(10)) {
  console.log(value); // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
}
// "done" is never reached

Конкатенация итерируемых объектов разных типов

Вы можете конкатенировать итерируемые объекты разных типов.

const array = [1, 2, 3];
const set = new Set([4, 5, 6]);
function* gen() {
  yield 7;
  yield 8;
  yield 9;
}

const it = Iterator.concat(array, set, gen());
console.log([...it]); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

Элементы каждого итерируемого объекта также могут быть разных типов, как и массивы.

const array = [1, "two", 3];
const set = new Set([true, {}]);

const it = Iterator.concat(array, set);
console.log([...it]); // [1, "two", 3, true, {}]

Конкатенация неитерируемых объектов

Неитерируемые объекты выбрасывают TypeError при передаче в Iterator.concat(), потому что у них нет метода [Symbol.iterator]().

const nonIterable = {
  next() {
    return { done: true };
  },
};

const it = Iterator.concat(nonIterable); // TypeError: object is not iterable

Поскольку все встроенные итераторы расширяют класс Iterator, они все являются итерируемыми и могут быть переданы в Iterator.concat().

const arrayIterator = [1, 2, 3][Symbol.iterator]();

const it = Iterator.concat(arrayIterator); // No error

Чтобы передать итератор, который также не является итерируемым, вы можете обернуть его с помощью Iterator.from().

const nonIterable = {
  next() {
    return { done: true };
  },
};

const it = Iterator.concat(Iterator.from(nonIterable)); // No error

Другой вариант — использовать вместо этого Iterator.prototype.flatMap(), который автоматически вызывает Iterator.from(). Но будьте осторожны: вам нужно вызвать flatMap() на итераторе, а не на массиве, потому что Array.prototype.flatMap() поддерживает только возвращаемые значения массивов.

const nonIterable = {
  next() {
    return { done: true };
  },
};

const it = [nonIterable].values().flatMap((x) => x); // No error

При реализации собственных итераторов рассмотрите возможность сделать их итерируемыми путем или наследования от Iterator или добавления метода [Symbol.iterator](), который возвращает this.

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-iterator.concat

Совместимость с браузерами

Десктопные Мобильные Серверные
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
concat
146
146
147
130
26.4
146
147
97
26.4
Нет
146
26.4
1.3.7
2.7.2
26.0.0

Смотрите также

  • Полифилл Iterator.concat в core-js
  • es-shims полифилл Iterator.concat
  • Iterator
  • Iterator.from()
  • Array.prototype.concat()

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/concat

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API