הצהרת function*
(מילת function
ולאחריה כוכבית) מגדירה פונקצית גנרטור, אשר מחזירה אובייקט Generator
.
The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.
ניתן גם להגדיר פונקציות גנרטור על-ידי שימוש בבנאי GeneratorFunction
, או בתחביר של ביטוי פונקציה.
תחביר
function* name([param[, param[, ... param]]]) { statements }
name
- שם הפונקציה.
param
- השם של פרמטר רשמי של הפונקציה.
statements
- הפקודות המרכיבות את גוף הפונקציה.
תיאור
גנרטורים הינם פונקציות שניתן לצאת מהן ולאחר מכן להיכנס אליהן מחדש. ההקשר שלהם (קשירת המשתנים) יישמר לאורך הכניסות מחדש.
גנרטורים ב- JavaScript -- במיוחד בשילוב עם Promises -- הינם כלי חזר מאוד לתכנות אסינכרוני, כיוון שהם מתווכים -- ואפילו מחסלים לחלוטין -- את הבעיות עם קריאות חוזרות, כגון Callback Hell ו- Inversion of Control.
תבנית זו הינה הבסיס לפונקציות async
.
קריאה לפונקצית גנרטור לא מריצה את גוף הפונקציה מיידית; במקום זאת, מוחזר אובייקט איטרטור לפונקציה. כאשר המתודה ()next
של האיטרטור נקראת, גוף הפונקציה רץ עד לביטוי ה-yield
הראשון, אשר מציין את הערך שיוחזר לאיטרטור, או העברה לפונקציה יוצרת אחרת על-ידי שימוש *yield
. מתודת ה- ()next
מחזירה אובייקט עם שדה value
, המכיל את הערך המיוצר ושדה done
בכעל ערך בוליאני, המציין האם הגנרטור יצר את הערך האחרון. קריאה למתודת ()next
עם ארגומנט תמשיך את ריצת פונקציית הגנרטור, תוך החלפת ביטוי ה- yield
בו הריצה הופסקה עם הארגומנט מתוך ()next
.
פקודת return
בתוך גנרטור, כאשר הוא רץ, תגרום לגנרטור לסיים (כלומר שדה ה- done
המוחזר יהיה בעל true
). אם ערך מוחזר, הוא יהיה בשדה value
של האובייקט המוחזר על-ידי הגנרטור.
בדומה לפקודת ה- return
, שגיאה שתיזרק בתוך הגנרטור תביא לסיום הגנרטור -- אלא אם היא תיתפס בגוף הגנרטור.
כאשר גנרטור מסתיים, קריאות נוספות ל- ()next
לא יגרמו לריצה כלשהי של קוד הגנרטור. הן רק יחזירו אובייקט בצורה זו: {value: undefined, done: true}
.
דוגמאות
דוגמה פשוטה
function* idMaker() {
var index = 0;
while (index < index+1)
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
// ...
דוגמה עם *yield
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('pretzel'); // 1 pretzel
gen.next('california'); // 2 california
gen.next('mayonnaise'); // 3 mayonnaise
פקודת return בתוך גנרטור
function* yieldAndReturn() {
yield "Y";
return "R";
yield "unreachable";
}
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 }
לא ניתן ליצור אובייקט גנרטור
function* f() {}
var obj = new f; // throws "TypeError: f is not a constructor
גנרטורים המוגדרים בתוך ביטוי
const foo = function* () {
yield 10;
yield 20;
};
const bar = foo();
console.log(bar.next()); // {value: 10, done: false}
מפרטים
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'function*' in that specification. |
Standard | הגדרה ראשונית. |
ECMAScript 2016 (ECMA-262) The definition of 'function*' in that specification. |
Standard | שונה, כך תהיה מלכודת שבגנרטורים לא [[Construct]] ויזרקו שגיאה בשימוש עם new . |
ECMAScript (ECMA-262) The definition of 'function*' in that specification. |
Living Standard |
תאימות לדפדפנים
BCD tables only load in the browser
הערות ספציפיות ל- Firefox
גנרטורים ואיטרטורים ב- Firefox לפני גרסה 26
גרסאות Firefox ישנות יותר מממשות הגדרת גנרטורים ישנה יותר. בגרסה הקודמת גנרטורים הוגדרו על-ידי שימוש במילת function
רגילה (ללא כוכבית), בין היתר. ראה פונקציה יוצרת מסורתית למידע נוסף.
אובייקט IteratorResult
מוחזר במקום זריקת שגיאה
החל מ- Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26), הפונקציה היוצרת המלאה כבר אינה זורקת TypeError
"generator has already finished". במקום זאת, היא מחזירה אובייקט IteratorResult
כדוגמת { value: undefined, done: true }
(bug 958951).
ראה גם
function* expression
- אובייקט
GeneratorFunction
- Iteration protocols
yield
*yield
Function
objectfunction declaration
function expression
Functions and function scope
- Other web resources:
- Regenerator an ES2015 generator compiler to ES5
- Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013
- Task.js
- Iterating generators asynchronously