Spec-Zone.ru › JavaScript

function*

Baseline Широко доступно

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

Объявление function* создает привязку новой функции-генератора к заданному имени. Функция-генератор может быть прервана и повторно начата позже, при этом ее контекст (привязки переменных) сохраняется между повторными запусками.

Вы также можете определять функции-генераторы с помощью function* выражения.

Попробуйте

function* generator(i) {
  yield i;
  yield i + 10;
}

const gen = generator(10);

console.log(gen.next().value);
// Expected output: 10

console.log(gen.next().value);
// Expected output: 20

Синтаксис

function* name(param0) {
  statements
}
function* name(param0, param1) {
  statements
}
function* name(param0, param1, /* …, */ paramN) {
  statements
}

Примечание: Функции-генераторы не имеют аналогов стрелочных функций.

Примечание: function и * являются отдельными токенами, поэтому их можно разделять пробельными символами или терминаторами строк.

Параметры

name
Имя функции.
param Необязательно
Имя формального параметра для функции. Синтаксис параметров см. в справке по функциям.
statements Необязательно
Инструкции, составляющие тело функции.

Описание

Объявление function* создает объект GeneratorFunction. Каждый раз, когда вызывается функция-генератор, она возвращает новый объект Generator, который соответствует протоколу итератора. Выполнение функции-генератора приостанавливается в некотором месте, которое изначально находится в самом начале тела функции. Функция-генератор может быть вызвана несколько раз для создания нескольких генераторов одновременно; каждый генератор поддерживает свой собственный контекст выполнения функции-генератора и может выполняться независимо.

Генератор обеспечивает двунаправленный поток управления: поток управления может передаваться между функцией-генератором (вызываемой стороной) и ее вызывающей стороной столько раз, сколько обе стороны пожелают. Поток управления может идти от вызывающей стороны к вызываемой стороной путем вызова методов генератора: next(), throw() и return(). Поток управления может идти от вызываемой стороны к вызывающей путем нормального завершения функции с помощью return или throw или выполнения всех инструкций, или с помощью выражений yield и yield*.

Когда вызывается метод next() генератора, тело функции-генератора выполняется до тех пор, пока не произойдет одно из следующих событий:

  • Выражение yield. В этом случае метод next() возвращает объект со свойством value, содержащим возвращаемое значение, и свойством done, которое всегда равно false. При следующем вызове next() выражение yield оценивается как значение, переданное в next().
  • yield*, делегирующий другому итератору. В этом случае этот вызов и любые будущие вызовы next() для генератора эквивалентны вызову next() для делегированного итератора до тех пор, пока делегированный итератор не будет завершен.
  • Оператор return (который не перехвачен try...catch...finally) или конец потока управления, что подразумевает return undefined. В этом случае генератор завершается, а метод next() возвращает объект со свойством value, содержащим возвращаемое значение, и свойством done, которое всегда равно true. Любые последующие вызовы next() не имеют эффекта и всегда возвращают { value: undefined, done: true }.
  • Возникает ошибка внутри функции, либо через оператор throw, либо через необработанное исключение. Метод next() выбрасывает эту ошибку, и генератор завершается. Любые последующие вызовы next() не имеют эффекта и всегда возвращают { value: undefined, done: true }.

Когда вызывается метод throw() генератора, он действует так, как если бы в теле генератора в текущей приостановленной позиции был вставлен оператор throw. Аналогично, когда вызывается метод return() генератора, он действует так, как если бы в теле генератора в текущей приостановленной позиции был вставлен оператор return. Оба метода обычно завершают генератор, если только функция-генератор не перехватывает завершение через try...catch...finally.

Генераторы ранее были парадигмой асинхронного программирования, позволяющей избежать Callback Hell путем достижения Инверсии управления. В настоящее время эта задача решается более простой моделью асинхронных функций и объектом Promise. Однако генераторы по-прежнему полезны для многих других задач, таких как простое определение итераторов.

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

Примеры

Базовый пример

function* idMaker() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// …

Пример с yield*

function* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function* generator(i) {
  yield i;
  yield* anotherGenerator(i);
  yield i + 10;
}

const gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20

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

function* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

const gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise

Оператор return в генераторе

function* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

const gen = yieldAndReturn();
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }

Генератор как свойство объекта

const someObj = {
  *generator() {
    yield "a";
    yield "b";
  },
};

const gen = someObj.generator();

console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }

Генератор как метод объекта

class Foo {
  *generator() {
    yield 1;
    yield 2;
    yield 3;
  }
}

const f = new Foo();
const gen = f.generator();

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

Генератор как вычисляемое свойство

class Foo {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
  }
}

const SomeObj = {
  *[Symbol.iterator]() {
    yield "a";
    yield "b";
  },
};

console.log(Array.from(new Foo())); // [ 1, 2 ]
console.log(Array.from(SomeObj)); // [ 'a', 'b' ]

Генераторы не являются конструкторами

function* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor

Пример генератора

function* powers(n) {
  // Endless loop to generate
  for (let current = n; ; current *= n) {
    yield current;
  }
}

for (const power of powers(2)) {
  // Controlling generator
  if (power > 32) {
    break;
  }
  console.log(power);
  // 2
  // 4
  // 8
  // 16
  // 32
}

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

Спецификация
ECMAScript® 2027 Language Specification
# sec-generator-function-definitions

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

Desktop Mobile Server
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
generator_function
39
13
26
26
10
39
26
26
10
4.0
39
10
1.0.0
1.0
4.0.0
IteratorResult_object
49
13
29
36
10
49
29
36
10
5.0
49
10
1.0.0
1.0
6.0.0
not_constructable_with_new
50
13
43
37
10
50
43
37
10
5.0
50
10
1.0.0
1.0
6.0.0
trailing_comma_in_parameters
58
14
52
45
10
58
52
43
10
7.0
58
10
1.0.0
1.0
8.0.0

См. также

  • Руководство по функциям
  • Руководство по итераторам и генераторам
  • Функции
  • GeneratorFunction
  • function* выражение
  • function
  • async function
  • async function*
  • Протоколы итерации
  • yield
  • yield*
  • Generator
  • Regenerator на GitHub
  • Promises and Generators: control flow utopia презентация Forbes Lindesay на JSConf (2013)
  • Task.js на GitHub
  • You Don't Know JS: Async & Performance, Ch.4: Generators от Kyle Simpson

© 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/Statements/function*

Spec-Zone.ru

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