Spread פורש אובייקט לתוך אובייקט אחר
תחביר ה-object spread, שלוש נקודות לפני אובייקט, מעתיק את המאפיינים העצמיים והברי-מנייה של אותו אובייקט לתוך ליטרל האובייקט שסביבו. זו הדרך הקצרה ביותר לשכפל, למזג ולייצר עותקים משונים בלי לגעת במקור.
ל-copy יש אותם מפתחות וערכים כמו ל-user, אבל זה אובייקט אחר. שינוי של אחד לא ישפיע על השני, לפחות ברמה העליונה. נחזור להסתייגות הזו בקרוב.
המודל המנטלי: { ...obj } אומר "שפכו את המאפיינים של obj לתוך ליטרל האובייקט החדש הזה". כל מה שתכתבו לצד ה-spread יהפוך לחלק מהתוצאה.
שכפול ודריסה בצעד אחד
הדפוס הנפוץ ביותר הוא לפרוש אובייקט ואז להוסיף או לדרוס כמה מאפיינים. המפתחות המאוחרים גוברים, אז פורשים קודם ודורסים אחר כך:
user לא השתנה. updated הוא אובייקט חדש שבו role הוחלף. דפוס העדכון הבלתי משתנה הזה מופיע בכל מקום ב-JavaScript מודרני: פונקציות עדכון state ב-React, reducers ב-Redux, וכל קוד שמעדיף לא לשנות נתונים במקום.
הפכו את הסדר ותקבלו את ההתנהגות ההפוכה:
כאן role: "guest" מגיע ראשון, אז user.role דורס אותו. שימושי כשרוצים ברירות מחדל שהאובייקט הנפרש יכול לדרוס.
מיזוג אובייקטים
פרשו שני אובייקטים (או יותר) לתוך ליטרל חדש כדי למזג אותם. אובייקטים מאוחרים דורסים מוקדמים במפתחות מתנגשים:
theme ו-fontSize מגיעים מ-userPrefs; debug נשאר מ-defaults. שלושה אובייקטים? ארבעה? אותו כלל: קוראים משמאל לימין, והכתיבה האחרונה גוברת.
זה התחליף המודרני ל-Object.assign({}, defaults, userPrefs). שניהם עושים אותו דבר, אבל גרסת ה-spread קלה יותר לקריאה ולא מפתה אתכם לבאג הנפוץ של כתיבת Object.assign(defaults, userPrefs), שמשנה את defaults.
Spread הוא העתקה רדודה
זה החלק שתופס אנשים. Spread מעתיק את המאפיינים ברמה העליונה של אובייקט. אם הערך של מאפיין הוא בעצמו אובייקט או מערך, מועתקת ההפניה, לא התוכן.
שינוי של copy.address.city שינה גם את user.address.city, כי שני האובייקטים חולקים את אותו אובייקט address. ה-spread נתן לנו רק מעטפת חיצונית חדשה.
כשצריך לשנות משהו מקונן, פרשו כל רמה שאתם רוצים לשנות:
לשכפול עמוק אמיתי של נתונים כלשהם, פנו ל-structuredClone(obj). הוא מטפל באובייקטים מקוננים, מערכים, תאריכים, maps ו-sets, והוא מובנה בכל סביבת ריצה מודרנית.
Spread מול Rest
הם חולקים את אותן שלוש נקודות אבל עושים דברים הפוכים. Spread פורש; rest אוסף.
כלל האצבע: אם ה-... נמצא בצד השמאלי של = (פירוק, destructuring), זה rest. אם הוא בתוך ליטרל של אובייקט או מערך בצד הימני, זה spread.
הסרת מאפיין בלי לשנות את המקור
שילוב של rest destructuring עם spread נותן לכם דרך נקייה לייצר עותק של אובייקט בלי מפתח אחד: בלי delete ובלי שינוי במקום:
tempToken נשלף למשתנה משלו (שאתם מתעלמים ממנו), וכל השאר נוחת ב-safe. ה-user המקורי לא השתנה.
מה Spread לא מעתיק
כמה דקויות ששווה להכיר:
- מאפיינים שאינם ברי-מנייה לא מועתקים. רוב המאפיינים שאתם יוצרים הם ברי-מנייה כברירת מחדל, אבל מאפיינים שהוגדרו עם
Object.definePropertyוחלק מהמובנים אינם כאלה. - ה-prototype לא מועתק.
{ ...instance }נותן לכם אובייקט רגיל, לא מופע של המחלקה המקורית. מתודות שהוגדרו על ה-prototype של המחלקה לא יהיו בעותק. - Getters מחושבים. פרישה של אובייקט עם getter קוראת ל-getter פעם אחת ושומרת את הערך המוחזר כמאפיין רגיל באובייקט החדש.
ל-copy יש x ו-y, אבל זה אובייקט רגיל: distance נמצאת על Point.prototype, ש-spread לא נגע בו. אם צריך לשכפל מופע של מחלקה, בדרך כלל המחלקה צריכה לספק מתודת clone משלה.
הבא בתור: מתודות של מערכים
Spread הוא חלק אחד מארגז הכלים לנתונים בלתי משתנים. החלק הגדול השני הוא מתודות של מערכים, map, filter, reduce וחברותיהן, שמייצרות מערכים חדשים במקום לשנות את המקוריים. זה העמוד הבא.
שאלות נפוצות
מה עושה ...obj ב-JavaScript?
בתוך ליטרל של אובייקט, ...obj מעתיק את כל המאפיינים העצמיים והברי-מנייה של האובייקט הזה לאובייקט החדש. { ...user } מייצר אובייקט חדש עם אותם מפתחות וערכים כמו user. זו הדרך המקובלת לשכפל או למזג אובייקטים בלי לשנות את המקוריים.
איך ממזגים שני אובייקטים ב-JavaScript?
פרשו את שניהם לתוך ליטרל אובייקט חדש: const merged = { ...a, ...b }. מאפיינים מ-b דורסים מפתחות תואמים מ-a, כי המאפיינים המאוחרים גוברים. זה שקול ל-Object.assign({}, a, b) אבל קריא יותר.
האם object spread הוא העתקה עמוקה?
לא. Object spread הוא העתקה רדודה: הוא מעתיק את המאפיינים ברמה העליונה, אבל אובייקטים ומערכים מקוננים עדיין משותפים דרך הפניה. שינוי של copy.address.city ישנה גם את original.address.city. להעתקה עמוקה אמיתית, השתמשו ב-structuredClone(obj).
מה ההבדל בין spread ל-rest?
הם נראים זהים (...) אבל עושים עבודות הפוכות. Spread פורש אובייקט או מערך למאפיינים או לאיברים בודדים: { ...user }. Rest אוסף את השאריות למשתנה אחד: const { name, ...others } = user. ההקשר אומר לכם במה מדובר.