אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » מדריכים » ECMAScript 6 » ECMAScript 6 – סקופ נפרד לכל בלוק עם let

ECMAScript 6 – סקופ נפרד לכל בלוק עם let

רן בר-זיק אוקטובר 9, 2016 8:30 am 2 תגובות

הגדרת משתנה שיש לו סקופ משלו בכל קטע קוד

המאמר הקודםECMAScript 6 – קבועים
המאמר הבאECMAScript 6 Promises
כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

במאמר הקודם למדנו על קבוע, במאמר הזה אנחנו נדבר על אחד מסימני ההיכר החזקים של ECMAScript 6 – הגדרת משתנה עם let.

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


"use strict";
var x = 5;

function moshe () {
  var x = 123;
  console.log(x); //Will be 123
}

console.log(x); //Will be 5
moshe();
console.log(x); //Will be 5

אם נפעיל את הקוד הבא (ואתם יכולים להעתיק ולהדביק אותו בקונסולה של כלי המפתחים), יהיה אפשר לראות שהקונסולה תראה לנו

5
123
5

למה? כי לפונקציה moshe יש סקופ משלה שבה המשתנה X נפרד לחלוטין ממשתנה X הגלובלי. בשניה שאנחנו מגדירים משתנה עם var בתוך פונקציה, אנחנו יוצרים משתנה פרטי בסקופ שאיתו אפשר לעבוד אבל הוא לא רלוונטי ל'עולם החיצוני' שמחוץ לפונקציה.

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

בואו ונדגים עם הקוד הבא:


"use strict";

 var x = 5;

if (true) {
  var x = 123;
  console.log(x); //Will be 123
}

console.log(x); //Will be 123

מה קורה פה? אנחנו מגדירים var בתוך ה-if, ל-if היה אמור להיות סקופ משלו. אבל אין כזה דבר ב-ECMAScript 5. לא יכולנו להגדיר scope משלנו מתי שבא לנו אלא רק בתוך פונקציה.

בדיוק בשביל זה יש לנו את ECMAScript 6 ואת let שמאפשר לנו להגדיר סקופ איפה שבא לנו. אפילו במשפט תנאי:


"use strict";

 var x = 5;

if (true) {
  let x = 123;
  console.log(x); //Will be 123
}

console.log(x); //Will be 5

אפשר להריץ את זה בקונסולה או לפתוח את הקונסולה שלכם ולראות את זה רץ ב-codepen:

See the Pen ECMAScript 6 – Let by Ran Bar-Zik (@barzik) on CodePen.

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


var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener('click', function() {
    console.log('You clicked button #' + i);
  });
}

הי הי הי! לא להתעלף פה! הקוד הזה די פשוט. מה שהוא עושה זה להשתמש בשאילתת JS פשוטה על מנת להכניס את כל אלמנטי ה-DOM שהם כפתורים אל מערך buttons. באמצעות לולאות for פשוטה אני מצמיד אירוע לחיצה לכל כפתור שמדפיס לקונסולה את המספר הסידורי של כל כפתור.

מה הבעיה? שועלי JS ותיקים כבר ידעו ישר. אבל למי שלא, העזרו ב-codepen הבא:

See the Pen ECMAScript 5 Scope failure by Ran Bar-Zik (@barzik) on CodePen.

לחיצה על הכפתור תראה לנו שבקונסולה אנחנו רואים כל פעם
"You clicked button #3"
בהנחה שיש שלושה כפתורים. אבל רגע, למה? למה אני לא רואה כל פעם את המספר של הכפתור שנלחץ? בדיוק בגלל בעית ה-scope! מחוץ ל-addEvent ה-i קבוע, אבל בתוך ההצמדה של האירוע ההתיחסות ל-i היא גלובלית. זה קשה להבנה באופן אינטואיטיבי, אבל כל מתכנת JS מספיק מנוסה נתקל בבעיה הזו.
יש כמה דרכים לפתור את זה, כולן דוחות למדי, למשל דרך אחת היא:


var buttons = document.getElementsByTagName('button');

for (var i = 0; i < buttons.length; i++) {
  bindEvent(i);
}

function bindEvent(k) {
  var button = buttons[k]
  button.addEventListener('click', function() {
    console.log(k);
  });
}

See the Pen ECMAScript 5 Scope failure – solution by Ran Bar-Zik (@barzik) on CodePen.

מה שקורה פה הוא שאנחנו בעצם מכריחים את JS ליצור סקופ חדש באמצעות הגדרת פונקציה. ואז ה-i שמשתמשים בו הוא מקומי ולא גלובלי. די פשוט (אם אתם יודעים את הפתרון) אבל מסובך למדי אם לא מבינים עד הסוף את עניין ה-scope או שאתם באמצע ראיון עבודה מלחיץ או שיש דד-ליין.

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


var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
  let j = i;
  buttons[j].addEventListener('click', function() {
    console.log('You clicked button #' + j);
  });
}

אתם מוזמנים לבחון את הפתרון כאן:

See the Pen ECMAScript 5 Scope failure solution by ES6 by Ran Bar-Zik (@barzik) on CodePen.

ההמלצה שלי? להתחיל להשתמש בזה, אין פלא שבכל פעם שאנחנו רואים הגדרה של משתנה ב-JavaScript יותר ויותר אנשים משתמשים ב-let על מנת להמנע מבלבול של ה-scope. יש לא מעט המלצות לוותר על ה-var לחלוטין.

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
למדריך המלא של ECMAScript 6
ECMAScript 6

2 תגובות

  1. Ron Apelbaum הגב אוקטובר 9, 2016 בשעה 9:36 am

    Greate example.
    Obviously the classic use should be inside the for loop itself:
    `for (let i = 0; i < buttons.length; i++)`…

  2. ailaG הגב אוקטובר 9, 2016 בשעה 5:32 pm

    אני הייתי משתמשת ב map, האמת, אבל אז זה לא ידגים את מה שרצית להסביר 🙂

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

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

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

גלילה לראש העמוד