function*

 

הצהרת function* (מילת function ולאחריה כוכבית) מגדירה פונקצית גנרטור, אשר מחזירה אובייקט Generator (en-US).

ניתן גם להגדיר פונקציות גנרטור על-ידי שימוש בבנאי GeneratorFunction, או בתחביר של ביטוי פונקציה.

תחביר

function* name([param[, param[, ... param]]]) {
   statements
}
name
שם הפונקציה.
param
השם של פרמטר רשמי של הפונקציה.
statements
הפקודות המרכיבות את גוף הפונקציה.

תיאור

גנרטורים הינם פונקציות שניתן לצאת מהן ולאחר מכן להיכנס אליהן מחדש. ההקשר שלהם (קשירת המשתנים) יישמר לאורך הכניסות מחדש.

גנרטורים ב- JavaScript -- במיוחד בשילוב עם Promises -- הינם כלי חזר מאוד לתכנות אסינכרוני, כיוון שהם מתווכים -- ואפילו מחסלים לחלוטין -- את הבעיות עם קריאות חוזרות, כגון Callback Hell ו- Inversion of Control.
תבנית זו הינה הבסיס לפונקציות async.

קריאה לפונקצית גנרטור לא מריצה את גוף הפונקציה מיידית; במקום זאת, מוחזר אובייקט איטרטור (en-US) לפונקציה. כאשר המתודה ()next של האיטרטור נקראת, גוף הפונקציה רץ עד לביטוי ה-yield (en-US) הראשון, אשר מציין את הערך שיוחזר לאיטרטור, או העברה לפונקציה יוצרת אחרת על-ידי שימוש *yield (en-US). מתודת ה- ()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).

ראה גם