Конструкция Yield * «переходит значение», если итеративный аргумент является функцией генератора - PullRequest
0 голосов
/ 25 февраля 2020

У меня неожиданное поведение со следующим кодом:

function* innerGeneratorFn() {
  yield 'foo';
  return 'bar';
}

function* outerGeneratorFn() {
  console.log('iter value:', yield* innerGeneratorFn());
}

for (const x of outerGeneratorFn()) {
  console.log('value:', x);
}

Конструкция yield * хочет Iterable, а innerGeneratorFn() - это Генератор объектов, который, в свою очередь, тоже Iterable. Значение yield * - это, вообще говоря, свойство value, сопровождающее done: true соответствующего итератора. Для классических итераторов это значение будет неопределенным. Но для итераторов, созданных из функции генератора, это значение будет иметь форму любого значения, возвращаемого функцией генератора (в данном случае innerGeneratorFn ()).

Вывод приведенного выше кода:

value: foo
iter value: bar

Вместо этого я бы ожидал следующий вывод:

value: foo
value: bar
iter value: bar

Действительно, эта похожая версия раннего кода:

function* innerGeneratorFn() {
  yield 'foo';
  return 'bar';
}

function* outerGeneratorFn() {
  console.log('iter value:', yield*['foo', 'bar']);
}

for (const x of outerGeneratorFn()) {
  console.log('value:', x);
}

Я получу в выводе:

value: foo
value: bar
iter value: undefined

Почему в первой версии кода вывод value : bar отсутствует?

1 Ответ

3 голосов
/ 25 февраля 2020

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

Звучит так, будто вы намеревались написать:

function* innerGeneratorFn() {
   yield 'foo';
   yield 'bar';
}

Который будет иметь желаемое поведение.

Обратите внимание, что вы также можете yield yield* innerGeneratorFn() выполнить sh То же самое без изменения innerGeneratorFn(), но я бы рассмотрел, чем анти-шаблон. Он будет работать только с функциями генератора, которые используют return, из которых на самом деле очень мало - и когда они это сделают, это будет по определенной причине c.


Дальнейшее чтение:

  • Итераторы и генераторы
  • function*, в котором говорится:

    A return оператор в генераторе после выполнения заставит генератор fini sh (то есть свойство done возвращаемого им объекта будет установлено в true). Если значение возвращено, оно будет установлено как свойство value объекта, возвращаемого генератором.

  • yield*, в котором говорится:

    Значение самого выражения yield* - это значение, возвращаемое этим итератором при его закрытии (т. Е. Когда done равно true).

...