ביטויי פונקציה

ביטויים של פונקציות הם פונקציות שנוצרות כאשר יש צורך בביטוי. לעיתים קרובות, ביטויי פונקציות מופיעים כערכים שהוקצו למשתנה. על אף שהצהרת פונקציה תמיד מחייבת שם, אפשר להשתמש בביטויי פונקציות כדי ליצור פונקציות אנונימיות על ידי השמטת המזהה והוספת מילת המפתח function ביחד עם צמדים של סוגריים שמכילים פרמטרים אופציונליים:

const myVariable = function() { };

לאחר מכן אפשר לקרוא לביטויי הפונקציות האלה באמצעות מזהה המשתנה:

const myVariable = function() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

אפשר גם להשתמש בביטויי פונקציות כדי ליצור פונקציות בעלות שם באמצעות תחביר דומה להצהרות של פונקציות:

const myVariable = function myFunction() {
    console.log( "This is my function." );
};

myVariable();
> "This is my function."

עם זאת, בניגוד להצהרות של פונקציות, אפשר לגשת לביטוי של פונקציה בעלת שם באמצעות שם הפונקציה רק בתוך הפונקציה עצמה:

const myVariable = function myFunction() {
  console.log( `I'm a ${ typeof myFunction }.`);
};

typeof myFunction;
> "undefined"

typeof myVariable;
> "function"

myVariable();
> "I'm a function."

שמות המשויכים לביטויים של פונקציות שימושיים בעיקר לניפוי באגים. ביטוי של פונקציה בעל שם יכול גם לקרוא לעצמו באופן רקורסיבי, אבל זה לא תרחיש נפוץ מאוד בפיתוח המודרני:

const myVariable = function myFunction() {
    console.log( "One second elapsed." );
    setTimeout( myFunction, 1000 );
};

setTimeout( myVariable, 1000 );
> "One second elapsed."
> "One second elapsed."
> "One second elapsed."
…

ביטויים של פונקציות חץ

הוספנו ב-ES6 ביטויים של פונקציות חצים (שנקראים גם 'פונקציות חץ', או לעיתים נדירות 'פונקציות למבדה'), כדי ליצור תחביר תמציתי ליצירת ביטויי פונקציות אנונימיים עם התנהגויות ייחודיות.

אפשר ליצור פונקציית חץ בכל מקום שבו צפוי ביטוי, לדוגמה, כערך שהוקצה למשתנה. בצורתה הנפוצה ביותר, פונקציית חץ מורכבת מזוג סוגריים מסולסלים שמכילים אפס פרמטרים או יותר, חץ שמורכב מסימן שווה יחיד ותו 'גדול מ-' (=>) וזוג סוגריים מסולסלים תואמים שמכילים את גוף הפונקציה:

const myFunction = () => {};

בתנאים מסוימים, ניתן להפוך את התחביר לקומפקטי עוד יותר. אם משתמשים רק בפרמטר אחד, אפשר להשמיט את הסוגריים ההתחלתיים:

const myFunction = myParameter => {};

כשרוצים שגוף הפונקציה יחזיר את הערך של ביטוי יחיד, לא צריך לתחום את גוף הפונקציה בסוגריים מסולסלים או במילת המפתח return:

const myFunction = () => 2 + 2

myFunction()
> 4

פונקציות החיצים הן ייחודיות כי אין להן הקשר משלהן לערכים arguments או this. במקום זאת, הם יורשים את שני הערכים מהסביבה הקסומה של פונקציית החץ, הפונקציה המקיפה הקרובה ביותר שמספקת את ההקשרים האלה.

function myParentFunction() {
    this.myProperty = true;
    let myFunction = () => {
            console.log( this );
    }
    myFunction();
};

let myInstance = new myParentFunction();
> Object { myProperty: true }

פונקציות חץ של שיחה

פונקציות חיצים לא מקשרים ארגומנטים באותו אופן כמו סוגי פונקציות אחרים. אובייקט arguments בגוף של פונקציית חץ יורש את הערך שלו מהסביבה הקרובה ביותר של פונקציית החץ:

function myFunction() {
    let myArrowFunction = () => {
            console.log( arguments[ 0 ] );
    }
    myArrowFunction( true );
};

myFunction( false );
> false

בדוגמה הזו, פונקציה חיצונית שנקראת עם הארגומנט false קוראת לפונקציית חץ פנימי עם הארגומנט true. מכיוון שהאובייקט arguments שבתוך פונקציית החץ, פונה לקישור בפונקציה החיצונית, הפונקציה הפנימית מתעדת את ה-false של הפונקציה החיצונית.

אם אין אובייקט arguments שיורש מהקשר ההורה, האובייקט arguments של פונקציית החץ לא מוגדר, וניסיון לגשת אליו יגרום לשגיאה:

let myArrowFunction = () => {
    console.log(arguments);
};
myArrowFunction( true );
> Uncaught ReferenceError: arguments is not defined

ביטויי פונקציות שמופעלים באופן מיידי (IIFE)

ביטוי פונקציה שמופעל מיד (IIFE), שלפעמים נקרא גם 'פונקציה אנונימית לביצוע עצמי', הוא ביטוי של פונקציה שנקרא מיד אחרי שמגדירים אותו. IIFE משתמש בביטוי פונקציה שנוצר על ידי סגירת הפונקציה באופרטור קיבוץ. זוג סוגריים נוסף תואם ולאחר מכן מפעיל את הפונקציה, מיד אחרי הגדרת הפונקציה עצמה או מיד אחרי אופרטור הקיבוץ. אם אתם משתמשים בפונקציה סטנדרטית, אין הבדל מעשי בין שתי הגישות:

(function() {
    console.log( "IIFE.")
    }
)();
> "IIFE."

(function() {
    console.log( "IIFE.")
    }
());
> "IIFE."

הדוגמה הראשונה קוראת לביטוי של הפונקציה המקובצת. בדוגמה השנייה קוראים להצהרת פונקציה בתוך האופרטורים של הקיבוץ, והתוצאה הסופית מוערכת כביטוי מקובץ. התוצאה זהה בשני המקרים.

עם זאת, יש הבדל כאשר ה-IIFE הוא פונקציית חץ. במקרה כזה, הסוגריים שמשמשים לקריאה לפונקציה חייבים להיות מחוץ לאופרטורים של הקיבוץ, כי פונקציית חץ בפני עצמה היא לא ביטוי, אבל צריך ליצור אותה בהקשר שבו צפוי ביטוי. אם תנסה לקרוא לפונקציית החץ מתוך ההיקף של אופרטורים של קיבוץ, התוצאה תהיה קריאה לפונקציית חץ שעדיין לא נוצרה בהקשר של ביטוי:

( () => {
    console.log( "IIFE." );
}() );
> Uncaught SyntaxError: missing ) in parenthetical

מכיוון שהאופרטורים של הקיבוץ מצפים לביטוי, פונקציית החץ בתוכם מוגדרת, והסוגריים שאחרים קוראים לביטוי המקובץ:

( () => {
    console.log( "IIFE." );
} )();
> "IIFE."

אפליקציות מדור קודם, IIFEs בשימוש לעיתים קרובות לניהול היקף, במיוחד כדי להימנע מזיהום ההיקף הגלובלי באמצעות משתנים עם היקף פונקציות והצהרות פונקציות. לפני ההשקה של היקף בלוקים ב-ES6, היה מקובל לעטוף סקריפט שלם ב-IIFE כדי למנוע זיהום מקרי בהיקף הגלובלי.

בחינת ההבנה

אפשר לקרוא לביטוי של פונקציה בעלת שם לפי שם מחוץ לפונקציה?

לא
כן