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!
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