> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/e-controls/e3-generators/07-generators-composition.md).

# 07. Generators Composition

Композиция — это естественное встраивание одного генератора в поток другого. При композиции значения из вложенного генератора выдаются «по мере готовности». Поэтому она будет работать даже если поток данных из вложенного генератора оказался бесконечным или ожидает какого-либо условия для завершения.

Для комбинирования используется специальная форма `yield*`. Она применима только к другому генератору и делегирует ему выполнение. То есть, при `yield*` интерпретатор переходит внутрь генератора-аргумента выполняет его, и все `yield`, которые он делает, выходят из внешнего генератора. Получается — как будто мы вставили код внутреннего генератора во внешний напрямую:

```javascript
function* foo() {
  yield "a";
  yield "b";
}

function* bar() {
  yield "x";
  yield* foo();
  yield "y";
}

const arr = [...bar()];
// ['x', 'a', 'b', 'y']
```

Внутри себя, `yield*` работает следующим образом:

```javascript
function* bar() {
  yield "x";
  for (const value of foo()) {
    yield value;
  }
  yield "y";
}
```

Значением `yield*` не обязательно должен быть генератор; это может быть любой итерируемый объект. Одно отличие в `yield*` от обычного в том, что этот операторы учитывает `return`-значение.

```javascript
function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) yield i;
}

function* generateAlphaNum() {
  // 0..9
  yield* generateSequence(48, 57);
  // A..Z
  yield* generateSequence(65, 90);
  // a..z
  yield* generateSequence(97, 122);
}

let str = "";
for (let code of generateAlphaNum()) {
  str += String.fromCharCode(code);
}
console.log(str); // 0..9A..Za..z
```
