הגדרת משתנים: המילים let ו const
החידוש הראשון שאני רוצה לדבר עליו הוא בתחום הגדרת המשתנים מאחר וזה החידוש שנתקלים בו מיד כשרואים קוד ES6.
1. מה רע ב var
והשאלה הראשונה לפני שבכלל נגיע לצורות חדשות להגדיר משתנים היא מה היה רע בדרך הישנה? למה var היה צריך ללכת?
והתשובה היא ש var הרגיז הרבה מאוד אנשים בגלל היותו מבלבל. דוגמא קלאסית אחת היא הקוד הזה שבאופן מפתיע עובד ומדפיס 10:
for (var i=0; i < 10; i++) {
// do stuff
}
console.log(i);
המשתנה שהוגדר באמצעות var מוכר בכל הפונקציה בה הוא הוגדר ולכן גם מחוץ ללולאה ניתן להדפיס את ערכו.
מוזרות נוספת ניתן לראות בקוד הבא:
console.log(i);
for (var i=0; i < 10; i++) {
// nothing special
}
הקוד עובד ומדפיס undefined, אבל כשמוחקים את הלולאה שורת ה console.log מפסיקה לעבוד בגלל שהמשתנה לא מוגדר. כלומר הלולאה (שמופיעה אחרי שורת ההדפסה) משפיעה על התנהגות של קוד שמופיעה לפניה.
מסיבות אלו וסיבות רבות נוספות מתכנני שפת JavaScript חיפשו לתקן את ההתנהגות של הגדרת משתנים ולאפשר הגדרת משתנה שתחום ההכרה שלו לא יחרוג מהבלוק בו הוא הוגדר. על הדרך הוחלט לפצל את הגדרת המשתנה ל-2 אפשרויות: const ו let.
2. המילה const
שפות תכנות רבות מאפשרות הגדרה חד-פעמית של משתנה או במילים אחרות הגדרת "קבוע". הקבוע הוא משתנה שמקבל ערך פעם אחת ואחרי שנתתם לו ערך לא ניתן להציב בו ערך אחר. הקוד הבא ממחיש הגדרת קבוע:
const name = 'ynon';
ניסיון לשנות את ערכו של הקבוע כך שיעבור להתיחס לערך אחר זורק שגיאה. הקוד הבא לדוגמא לא יעבוד:
const name = 'ynon';
name = 10;
מה שיפה כאן שהגדרת const משפיעה על הבלוק בו נכתבה בלבד. כך הקוד הבא יעבוד וידפיס את שני השמות:
if (2 < 5) {
const p = 'foo';
console.log(p);
}
if (2 < 5) {
const p = 'bar';
console.log(p);
}
חשוב לשים לב שהעובדה שמשתנה מוגדר באמצעות const לא אומרת כלום על שינוי הערך עצמו אליו הוא מתיחס. מערך לדוגמא הוא אוביקט שיכול להשתנות ולכן הקוד הבא עובד:
const p = [];
p.push(10);
p.push(20);
console.log(p);
המשתנה p
ממשיך להתיחס לאותו מערך לאורך כל ריצת התוכנית, זה פשוט תוכן המערך עצמו שמשתנה. אותו מנגנון קיים גם בעת שימוש באוביקטים ולכן גם הקוד הבא עובד:
const p = { x: 10, y: 20 };
p.x = 30;
console.log(p);
3. המילה let
הדרך השניה להגדיר משתנה היא הפקודה let
. פקודה זו מגדירה משתנה שבאמת משנה את ערכו לאורך חיי התוכנית, לדוגמא משתנה רץ בלולאה. הקוד הבא עובד ומגדיר את i כמשתנה רץ:
for (let i=0; i < 10; i++) {
console.log(i);
}
בדומה ל const גם משתנה שהוגדר עם let
מוכר רק בתחום בו הוא הוגדר ולכן הקוד הבא לא יעבוד:
for (let i=0; i < 10; i++) {
console.log(i);
}
console.log(i);
הקוד מדפיס את המספרים מ-0 עד 9 ולאחר מכן את השגיאה:
ReferenceError: Can't find variable: i
4. מתי נשתמש בכל שיטה
הגישה שלי לשתי המילים החדשות היא להעדיף את const בכל מקרה שרק אפשר. הסיבה ש const הוא נוקשה יותר ולכן קל יותר לקרוא את הקוד כשהמשתנים מוגדרים עם const ואתה יודע שיש למשתנה רק ערך אפשרי יחיד.
בגלל שהגדרת המשתנה רלוונטית רק לבלוק בו היא נכתבה אני משתדל להגדיר משתנים בבלוק הפנימי ביותר בו הם דרושים. בצורה כזאת בדרך כלל מאוד ברור מה מטרת המשתנה והשימוש ב const אוכף את השימוש המוגבל בו רק למטרה אליה התכוונתי.
הגישה שלי לשתי המילים החדשות היא להעדיף את const בכל מקרה שרק אפשר. הסיבה ש const הוא נוקשה יותר ולכן קל יותר לקרוא את הקוד כשהמשתנים מוגדרים עם const ואתה יודע שיש למשתנה רק ערך אפשרי יחיד.
בגלל שהגדרת המשתנה רלוונטית רק לבלוק בו היא נכתבה אני משתדל להגדיר משתנים בבלוק הפנימי ביותר בו הם דרושים. בצורה כזאת בדרך כלל מאוד ברור מה מטרת המשתנה והשימוש ב const אוכף את השימוש המוגבל בו רק למטרה אליה התכוונתי.