Menu

אופרטורי השוואה ב-JavaScript: == מול === ו-Object.is

איך שוויון עובד ב-JavaScript: השוואה מחמירה מול השוואה רופפת, המוזרויות של ==, איך NaN ואובייקטים מתנהגים, ומתי להשתמש ב-Object.is.

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

שתי דרכים לשאול "האם אלה שווים?"

JavaScript נותנת שני אופרטורי שוויון: === (מחמיר) ו-== (רופף). הם נראים כמעט זהים. הם מתנהגים שונה מאוד.

=== בודק אם לשני האופרנדים יש אותו טיפוס וגם אותו ערך. == ממיר קודם את האופרנדים לטיפוס משותף, ורק אז משווה. ההמרה הזו, type coercion, היא המקור לרוב המוניטין של JavaScript בנושא שוויון.

הגרסה הקצרה: השתמשו ב-=== כברירת מחדל. את הגרסה הארוכה שווה לקרוא פעם אחת, כדי לדעת ממה אתם מוותרים.

שוויון מחמיר: מה שכנראה תרצו

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

אם הטיפוסים לא תואמים, התשובה היא false מיד. אם הם תואמים, JavaScript משווה את הערכים. בערכים פרימיטיביים זו השוואת ערכים; באובייקטים זו השוואת הפניות (עוד על זה בעוד רגע).

!== הוא אופרטור אי השוויון המחמיר, והוא פועל לפי אותם כללים בכיוון ההפוך.

שוויון רופף: המרה בתחפושת

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

הכללים המדויקים נמצאים במפרט, והם לא נוראיים, אבל לזכור אותם באמצע דיבוג זה סיפור אחר. העובדה ש-"0" == false הוא true תופסת גם מפתחים מנוסים. כך גם [] == false (גם true, כי המערך מומר ל-"", שמומר ל-0).

זו הסיבה שרוב מדריכי הסגנון, וגם הכלל eqeqeq של ESLint, אומרים להשתמש ב-=== כברירת מחדל. אתם משלמים בתו אחד נוסף ומקבלים כללים שאפשר באמת לזכור.

התבנית השימושית היחידה של ==

יש ביטוי אחד של שוויון רופף ששווה להכיר: x == null מחזיר true כש-x הוא null או undefined, ו-false בכל מקרה אחר.

המקבילה המחמירה היא x === null || x === undefined, שעובדת אבל רועשת יותר לקריאה. בהרבה בסיסי קוד == null הוא החריג המבורך היחיד. בחרו כלל ויישמו אותו בעקביות.

אובייקטים מושווים לפי הפניה

באובייקטים, במערכים ובפונקציות, גם === וגם == שואלים את אותה שאלה: "האם שני הצדדים מצביעים לאותו אובייקט בזיכרון?" ולא "האם יש להם אותו תוכן?"

שני object literals עם תוכן זהה הם עדיין שני אובייקטים שונים. זה מכשיל כל אחד לפחות פעם אחת.

להשוואה לפי ערך, כתבו פונקציית עזר משלכם, השתמשו בספרייה (lodash.isequal), או סרלזו עם JSON.stringify לאובייקטים פשוטים:

JSON.stringify עובד רק עם נתונים פשוטים: הוא מתעלם מפונקציות, מ-undefined ומ-symbols, ולא מבטיח סדר מפתחות זהה בין מנועים בכל הצורות. זו בדיקה מהירה, לא פתרון כללי.

NaN לא שווה לשום דבר

NaN ("not a number") הוא הערך ש-JavaScript מחזירה כשלפעולה מספרית אין תשובה בעלת משמעות: 0/0, Number("abc"), Math.sqrt(-1). שני אופרטורי השוויון מחזירים false כשאחד הצדדים הוא NaN, כולל כששני הצדדים הם NaN:

כדי לזהות NaN, השתמשו ב-Number.isNaN(value). אל תשתמשו בפונקציה הגלובלית הישנה isNaN: היא ממירה קודם את הארגומנט שלה, ולכן isNaN("hello") מחזיר true, וזה כמעט אף פעם לא מה שרוצים.

Object.is: כמעט ===, עם שני תיקונים

Object.is(a, b) מתנהג כמו === חוץ משני מקרי קצה:

ברוב הזמן === הוא מה שרוצים. השתמשו ב-Object.is כשצריך במפורש להתייחס ל-NaN כשווה לעצמו, או להבחין בין +0 ל--0: שני המקרים נדירים, ושניהם חשובים לפעמים בקוד מספרי ובמנגנונים הפנימיים של frameworks (React משתמשת ב-Object.is להשוואות של state).

אופרטורי אי שוויון מתחלקים באותו אופן

!== הוא מחמיר, != הוא רופף, ואותה עצה חלה:

השתמשו ב-!== כברירת מחדל. אם כבר התרתם == null, אפשר להתיר גם את המקבילה שלו != null לבדיקה של "לא null וגם לא undefined".

רשימת בדיקה להשוואת ערכים

כשצריך להשוות שני ערכים, עברו על הרשימה הזו:

  • ערכים פרימיטיביים, מצפים לאותו טיפוס? השתמשו ב-===.
  • בודקים null או undefined? x == null בסדר אם מדריך הסגנון שלכם מתיר זאת; אחרת x === null || x === undefined.
  • בודקים NaN? Number.isNaN(x).
  • משווים אובייקטים לפי זהות? === עושה בדיוק מה שרוצים.
  • משווים אובייקטים לפי תוכן? כתבו פונקציית עזר, השתמשו בספרייה, או סרלזו. האופרטורים המובנים לא יעזרו כאן.

היצמדו ל-===, התייחסו ל-== ככלי מיוחד למקרה של == null, ותתחמקו מהמוזרויות של שוויון שממלאות את רשימות השאלות הנפוצות על JavaScript.

הבא בתור: אופרטורים

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

שאלות נפוצות

מה ההבדל בין == ל-=== ב-JavaScript?

=== הוא שוויון מחמיר: הוא מחזיר true רק אם לשני האופרנדים יש אותו טיפוס ואותו ערך. == הוא שוויון רופף: הוא ממיר את האופרנדים לאותו טיפוס לפני ההשוואה. 1 === '1' הוא false, אבל 1 == '1' הוא true, כי == ממיר קודם את המחרוזת למספר.

האם תמיד כדאי להשתמש ב-=== ב-JavaScript?

כברירת מחדל, כן. === צפוי, והכללים שלו קלים לזכירה. החריג הנפוץ היחיד הוא x == null, שנוח כי הוא תופס גם null וגם undefined. רוב ה-linters (הכלל eqeqeq של ESLint) אוכפים === ומאפשרים את התבנית הזו כחריג אופציונלי.

למה NaN === NaN מחזיר false?

תקן IEEE 754 קובע ש-NaN לא שווה לשום דבר, כולל לעצמו. לכן כל אופרטור שוויון מחזיר false כשמעורב NaN. השתמשו ב-Number.isNaN(x) כדי לבדוק אם ערך הוא NaN, או ב-Object.is(NaN, NaN), שמחזיר true.

איך משווים שני אובייקטים ב-JavaScript?

גם == וגם === משווים אובייקטים לפי הפניה, לא לפי תוכן. {a: 1} === {a: 1} הוא false כי אלה שני אובייקטים שונים. כדי להשוות לפי ערך צריך לכתוב בדיקה משלכם, להשתמש בספרייה כמו isEqual של Lodash, או לסרלז עם JSON.stringify לאובייקטים פשוטים.

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

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

להתחיל