yield*

Выражение yield* используется для того, чтобы "передать управление" функцией-генератором другому генератору или итерируемому объекту.

Синтаксис

 yield* [[expression]];
expression
Итерируемый объект

Описание

Выражение yield* в функции-генераторе принимает итерируемый объект и возвращает его значения по очереди, как если бы эта функция-генератор возвращала их сама.

Значение выражения yield* само по себе равно последнему значению итерируемого объекта (т.е., того когда done равно true).

Примеры

Передача другому генератору

В следующем примере, значения полученные из g1() возвращаются из g2 вызовами next, как будто бы она вычислила их сама.

function* g1() {
  yield 2;
  yield 3;
  yield 4;
}

function* g2() {
  yield 1;
  yield* g1();
  yield 5;
}

var iterator = g2();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: 4, done: false }
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Другие итерируемые объекты

Помимо объектов генераторов, yield* может перебирать другие виды итерируемых объектов, т.е. массивы, строки, объекты аргументов и др.

function* g3() {
  yield* [1, 2];
  yield* "34";
  yield* Array.from(arguments);
  // Определение этого итератора ниже
  yield* new PowesOfTwo(4)
}

var iterator = g3(5, 6);

// Значения из массива
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
// Из строки
console.log(iterator.next()); // { value: "3", done: false }
console.log(iterator.next()); // { value: "4", done: false }
// Из аргументов
console.log(iterator.next()); // { value: 5, done: false }
console.log(iterator.next()); // { value: 6, done: false }
// Из специального итератора
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 4, done: false }

console.log(iterator.next()); // { value: undefined, done: true }

// Итератор, который возвращает все степени двойки
// до maximum включительно
class PowersOfTwo {
  constructor(maximum) {
    this.maximum = maximum
    this.value = 1
  }
  [Symbol.iterator]() {
    const self = this
    return {
      next() {
        if(self.value > self.maximum) return { done: true }

        const value = self.value
        self.value *= 2
        return { done: false, value }
      }
    }
  }
}

Собственное значение выражения yield*

yield* - это выражение, а не оператор, поэтому оно имеет значение, равное последнему значению итератора 

function* g4() {
  yield* [1, 2, 3];
  return "foo";
}

var result;

function* g5() {
  result = yield* g4();
}

var iterator = g5();

console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true },
                              // g4() в этой точке вернёт { value: "foo", done: true }

console.log(result);          // "foo"

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

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'Yield' в этой спецификации.
Стандарт Initial definition.
ECMAScript (ECMA-262)
Определение 'Yield' в этой спецификации.
Живой стандарт

Поддержка браузерами

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help! (en-US)

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support (Да) 27.0 (27.0) ? ? ?
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Да) 27.0 (27.0) ? ? ?

Специфичные для Firefox примечания

  • Начиная с Gecko 33 (Firefox 33 / Thunderbird 33 / SeaMonkey 2.30), разбор выражений yield было приведено к соответствию с последними спецификациями ES6 (баг 981599):
    • Реализована корректная обработка разрыва строки. Разрыва строки между "yield" и "*" быть не может. Такой код вызовет SyntaxError:
      function* foo() {
        yield
        *[];
      }

See also