Menu

for...of ו-for...in ב-JavaScript: מעבר על מערכים ואובייקטים

ההבדל האמיתי בין for...of ל-for...in ב-JavaScript: ערכים מול מפתחות, מערכים מול אובייקטים, ומתי להשתמש בכל אחת.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

שתי לולאות, שני תפקידים שונים

ל-JavaScript יש שתי צורות לולאה שנראות כמעט זהות אבל עושות דברים שונים מאוד. for...of עוברת על הערכים של אובייקט איטרבילי. for...in עוברת על המפתחות של אובייקט. הבדל של מילה קטנה אחת, והתנהגות שונה לגמרי.

הנה כל הסיפור בדוגמה אחת:

הלולאה הראשונה מדפיסה apple, banana, cherry: הערכים. השנייה מדפיסה 0, 1, 2: המפתחות, כמחרוזות. בחרו בלולאה הלא נכונה ותבזבזו עשר דקות בתהייה למה המערך שלכם מלא במספרים.

for...of: ערכים מכל דבר איטרבילי

for...of היא הלולאה שתשתמשו בה הכי הרבה. היא עובדת על כל מה ש-JavaScript מחשיבה איטרבילי: מערכים, מחרוזות, Map, Set, NodeList, גנרטורים ועוד.

בלי להתעסק עם אינדקסים, בלי scores[i]. מבקשים כל ערך, ומקבלים כל ערך. גם מחרוזות הן איטרביליות, ו-for...of עוברת עליהן תו אחרי תו:

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

קבלת האינדקס עם for...of

הדבר היחיד ש-for...of לא נותנת ישירות הוא המיקום. כשצריך אותו, שלבו את הלולאה עם entries():

names.entries() מפיקה זוגות [index, value], והפירוק (destructuring) בצד ההגדרה מפצל אותם לשני משתנים. בדרך כלל זה נקי יותר מלחזור ללולאה קלאסית for (let i = 0; ...) רק כי צריך את i.

for...in: מפתחות של אובייקט

for...in נבנתה בשביל אובייקטים רגילים. היא עוברת על מפתחות המחרוזת שניתנים למנייה:

שימו לב שמקבלים את המפתח, לא את הערך. כדי לקרוא את הערך ניגשים שוב לאובייקט עם user[key]. כל מפתח הוא מחרוזת, גם אם הוא נראה כמו מספר.

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

Object.hasOwn(user, key) מדלגת על כל מה שעבר בירושה. בקוד מודרני רוב המפתחים נמנעים מ-for...in לגמרי ומשתמשים במקומה ב-Object.keys, Object.values או Object.entries, וזה מביא אותנו לחלק הבא.

הדרך המודרנית לעבור על אובייקט

במקום for...in, שלבו את for...of עם אחת מפונקציות העזר של Object.*. בחרו את זו מבין השלוש שמתאימה למה שאתם צריכים:

Object.entries נוחה במיוחד: פירוק הזוג [key, value] נקרא כמעט כמו שפה רגילה. ומכיוון שהמתודות האלה מחזירות רק את המאפיינים של האובייקט עצמו שניתנים למנייה, אין צורך לדאוג מזבל שעבר בירושה.

אל תשתמשו ב-for...in על מערכים

זה חוקי טכנית, אבל זה מכשיל אנשים:

מקבלים 0, 1, 2, וגם tag. כל מאפיין שמישהו הצמיד למערך, או ל-Array.prototype דרך polyfill, יופיע גם הוא. המפתחות הם מחרוזות, ולכן key + 1 משרשר במקום לחבר. וסדר המעבר לא מובטח להתאים לסדר המערך בכל מקרי הקצה.

כלל אצבע:

  • ערכים של מערך? for...of arr.
  • אינדקס וערך של מערך? for...of arr.entries().
  • רק אינדקס, לספירה? לולאה קלאסית for (let i = 0; i < arr.length; i++).
  • מפתחות או זוגות של אובייקט? Object.keys(obj) / Object.entries(obj) עם for...of.

בקיצור: for...in היא כלי נישתי. for...of יחד עם פונקציות העזר של Object מכסות את כל מה שצריך.

break ו-continue עובדות בשתיהן

שתי הלולאות תומכות בכלים הרגילים ליציאה מוקדמת:

continue מדלגת לאיטרציה הבאה, ו-break יוצאת מהלולאה לגמרי. זו הסיבה העיקרית להעדיף את for...of על פני .forEach(): ב-callback של forEach אי אפשר לעשות break מהלולאה, אבל ב-for...of אפשר.

סיכום זה לצד זה

ארבע לולאות, ארבעה תפקידים, מודל חשיבה אחד: אם אתם רוצים ערכים ממשהו איטרבילי, השתמשו ב-for...of. אם אתם רוצים לעבוד עם המאפיינים של אובייקט, עברו דרך Object.keys / Object.values / Object.entries, גם כן עם for...of. השאירו את for...in למקרה הנדיר שבו באמת רוצים כל מפתח מחרוזת של אובייקט שניתן למנייה, בירושה או לא.

הבא בתור: Truthy ו-Falsy

כל לולאה וכל if ב-JavaScript שואלים בסוף אותה שאלה: האם הערך הזה נחשב אמת? התשובה לא תמיד ברורה: מחרוזות ריקות, אפס, null ו-undefined מתנהגים אחרת ממה שאולי הייתם מצפים. ערכי truthy ו-falsy הם הנושא הבא.

שאלות נפוצות

מה ההבדל בין for...of ל-for...in ב-JavaScript?

for...of עוברת על הערכים של אובייקט איטרבילי כמו מערך, מחרוזת, Map או Set. for...in עוברת על המפתחות (שמות המאפיינים) של אובייקט. עבור המערך ['a', 'b'], for...of נותנת את 'a' ו-'b', ואילו for...in נותנת את '0' ו-'1' כמחרוזות.

אפשר להשתמש ב-for...of על אובייקט?

לא ישירות: אובייקטים רגילים אינם איטרביליים. השתמשו ב-Object.keys(obj), Object.values(obj) או Object.entries(obj) כדי לקבל מערך שאפשר לעבור עליו עם for...of. התבנית הנפוצה היא for (const [key, value] of Object.entries(obj)).

למה לא כדאי להשתמש ב-for...in על מערכים?

טכנית זה עובד, אבל for...in עוברת על כל מאפיין שניתן למנייה, כולל מאפיינים שעברו בירושה וכל תוספת שמישהו הכניס ל-Array.prototype. היא גם מחזירה את המפתחות כמחרוזות, והסדר לא מובטח במלואו בכל מקרה עבור מפתחות שנראים כמו מספרים שלמים. השתמשו ב-for...of בשביל ערכים, או בלולאת for קלאסית כשצריך את האינדקס.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל