function*

 

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

ניתן גם להגדיר פונקציות גנרטור על-ידי שימוש בבנאי 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 Latest Draft (ECMA-262)
The definition of 'function*' in that specification.
Draft  

תאימות לדפדפנים

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
function*Chrome Full support 39Edge Full support 13Firefox Full support 26IE No support NoOpera Full support 26Safari Full support 10WebView Android Full support YesChrome Android Full support 39Firefox Android Full support 26Opera Android Full support YesSafari iOS Full support 10Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Full support 4.0.0
Full support 0.12
Disabled
Disabled From version 0.12: this feature is behind the --harmony runtime flag.
IteratorResult object instead of throwingChrome Full support 49Edge Full support 13Firefox Full support 29IE No support NoOpera Full support YesSafari Full support YesWebView Android Full support YesChrome Android Full support 49Firefox Android Full support 29Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support Yesnodejs Full support Yes
Not constructable with new (ES2016)Chrome Full support 50Edge Full support 13Firefox Full support 43IE No support NoOpera Full support 37Safari Full support 10WebView Android Full support 50Chrome Android Full support 50Firefox Android Full support 43Opera Android Full support 37Safari iOS Full support 10Samsung Internet Android Full support 5.0nodejs Full support Yes
Trailing comma in parametersChrome Full support 58Edge Full support 14Firefox Full support 52IE No support NoOpera Full support 45Safari ? WebView Android Full support 58Chrome Android Full support 58Firefox Android Full support 52Opera Android Full support 43Safari iOS ? Samsung Internet Android Full support 7.0nodejs Full support 8.0.0

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
User must explicitly enable this feature.
User must explicitly enable this feature.

הערות ספציפיות ל- 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).

ראה גם