--- title: function* slug: Web/JavaScript/Reference/Statements/function* tags: - ECMAScript 2015 - Function - JavaScript - Ітератор - генератор translation_of: Web/JavaScript/Reference/Statements/function* ---
Оголошення function*
(ключове слово function
з зірочкою) визначає функцію-генератор, яка повертає об'єкт {{jsxref("Global_Objects/Generator","Generator")}}.
Ви також можете визначати функції-генератори за допомогою конструктора {{jsxref("GeneratorFunction")}} або функціонального виразу.
function* name([param[, param[, ... param]]]) { statements }
name
param
statements
Генератори - це функції, з яких можна вийти та пізніше повторно зайти. Їхній контекст (зв'язування змінних) збережеться між заходами.
Генератори у JavaScript -- особливо у поєднанні з промісами -- дуже потужний інструмент асинхронного програмування, бо вони пом'якшують -- якщо не усувають повністю -- проблеми зворотних викликів, такі як Пекло зворотних викликів та Інверсія управління.
Виклик функції-генератора не виконує тіло функції негайно; замість цього повертається об'єкт-ітератор для функції. Коли викликається метод ітератора next()
, тіло функції-генератора виконується до першого виразу {{jsxref("Operators/yield", "yield")}}, який визначає значення, що має бути повернене ітератором, або, оператором {{jsxref("Operators/yield*", "yield*")}}, делегується до іншої функції-генератора. Метод next()
повертає об'єкт з властивістю value
, що містить отримане значення, та властивістю done
, яка вказує, чи генератор віддав останнє значення, у вигляді булевого значення. Виклик метода next()
з аргументом відновить виконання функції-генератора, замінюючи вираз yield
в тій точці, де виконання було призупинене, аргументом з next()
.
Оператор return
у генераторі змусить генератор завершити виконання (тобто, властивості done
поверненого об'єкта буде присвоєне значення true
). Якщо повертається значення, воно буде присвоєте властивості value
об'єкта, що повертається генератором.
Схоже на оператор return
, викидання помилки всередині генератора змусить генератор завершити виконання -- якщо не буде перехоплене у тілі генератора.
Коли генератор завершує виконання, наступні виклики next
не виконають жодного коду генератора, вони лише повернуть об'єкт наступного вигляду: {value: undefined, done: true}
.
function* idMaker() { var index = 0; while (true) yield index++; } var 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 // ...
function* anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3; } function* generator(i) { yield i; yield* anotherGenerator(i); yield i + 10; } var 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); } var gen = logGenerator(); // перший виклик метода next виконує функцію з початку // до першого оператора yield gen.next(); // 0 gen.next('крендель'); // 1 крендель gen.next('кава'); // 2 кава gen.next('майонез'); // 3 майонез
function* yieldAndReturn() { yield "Y"; return "R"; yield "недосяжний"; } var 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 'а'; yield 'б'; } } const gen = someObj.generator() console.log(gen.next()); // { value: 'а', done: false } console.log(gen.next()); // { value: 'б', 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 'а'; yield 'б'; } } console.log(Array.from(new Foo)); // [ 1, 2 ] console.log(Array.from(SomeObj)); // [ 'а', 'б' ]
function* f() {} var obj = new f; // викидає "TypeError: f is not a constructor
const foo = function* () { yield 10; yield 20; }; const bar = foo(); console.log(bar.next()); // {value: 10, done: false}
Специфікація | Статус | Коментар |
---|---|---|
{{SpecName('ES2015', '#sec-generator-function-definitions', 'function*')}} | {{Spec2('ES2015')}} | Початкове визначення. |
{{SpecName('ES2016', '#sec-generator-function-definitions', 'function*')}} | {{Spec2('ES2016')}} | Внесено зміни, що генератори не повинні мати пастки [[Construct]] та викидатимуть помилку при використанні з new . |
{{SpecName('ESDraft', '#sec-generator-function-definitions', 'function*')}} | {{Spec2('ESDraft')}} |
{{Compat("javascript.statements.generator_function")}}
Старші версії Firefox реалізують старшу версію пропозиції генераторів. У старшій версії генератори визначались за допомогою звичайного ключового слова function
(без зірочки), серед інших відмінностей. Дивіться більше інформації у статті Застаріла функція-генератор.
IteratorResult
Починаючи з Gecko 29 {{geckoRelease(29)}}, завершена функція-генератор більше не викидає помилку {{jsxref("TypeError")}} "generator has already finished". Замість цього, вона повертає об'єкт IteratorResult
у вигляді { value: undefined, done: true }
({{bug(958951)}}).