שכפול אובייקטים ב-JavaScript

שכפול של אובייקט ב-JavaScript לא נשמע כמו משהו מסובך במיוחד.
האמת? נכון, זה לא מסובך אבל זה כן טריקי. למה ואיך בפוסט הבא.

נתחיל מהבסיס…

אם ארצה לשכפל אובייקט אוכל לעשות את הדבר הפשוט הבא:

let obj1 = {
    'name': 'John',
    'age': 30
};
let obj2 = obj1;
console.log(obj1, obj2);

והפלט:

ניתן לראות שהאובייקט obj1 הועתק אל האובייקט obj2.
ניתן לראות שהאובייקט obj1 הועתק אל האובייקט obj2.

וכמובן שלאחר העתקה ניתן לשנות את ערך של property מסוים, כך:

let obj1 = {
    'name': 'John',
    'age': 30
};
let obj2 = obj1;
obj1.age = 32;
console.log(obj1);
console.log(obj2);

ובוודאי שזה מה שנקבל בפלט:

ניתן לראות שה-property בשם age שונה עבור שני האובייקטים.
ניתן לראות שה-property בשם age שונה עבור שני האובייקטים.

רגע..מה?
מדוע age השתנה מ-30 ל-32 בשני האובייקטים? פשוט מאוד, כי אובייקטים הם Reference ולא Primitive.
אם זה לא ברור, זה בדיוק הזמן לעצור עם מאמר זה ולקרוא את המאמר שכתבתי בנושא: זהירות, זה מבלבל: ההבדל בין Value ל- Reference ב-JavaScript

יש? בואו נמשיך.

אז מה ניתן לעשות אתם שואלים?
להשתמש ב-Object.assign למשל:

let obj1 = {
    'name': 'John',
    'age': 30
};
let obj2 = Object.assign({}, obj1);
obj1.age = 32;
console.log(obj1);
console.log(obj2);

ועכשיו הפלט נראה כך:

לאחר השימוש ב-Object.assign ה-age השתנה רק עבור obj1.
לאחר השימוש ב-Object.assign ה-age השתנה רק עבור obj1.

ויש אפילו דרך פשוטה יותר…

באמצעות Spread Operator (לא יודעים מה זה Spread Operator? לא נורא, גם על זה כתבתי פוסט: Spread Operator ב-JavaScript) ניתן לעשות את אותה הפעולה בצורה פשוטה יותר:

let obj1 = {
    'name': 'John',
    'age': 30
};
let obj2 = {...obj1};

מה טריקי פה?

אז כן, Object.assign או Spread Operator לא פותרים את הבעיה לגמרי, למה?
בבקשה:

let obj1 = {
    'name': 'John',
    'age': 30,
    'food': ['Pizza', 'Salad', 'Burger']
};
let obj2 = {...obj1};
obj1.food[0] = 'Pasta';
console.log(obj1);
console.log(obj2);

והפלט:

האיבר הראשון המערך food שונה מ-Pizza ל-Pasta עבור שני האובייקטים.
האיבר הראשון המערך food שונה מ-Pizza ל-Pasta עבור שני האובייקטים.

חזרנו אחורה.
הכוונה הייתה לשנות את האיבר הראשון במערך food של האובייקט obj1 בלבד, אז למה זה שוב השתנה בשני האובייקטים?
שוב, כי גם מערכים הם Reference ולא Primitive, ו-food הוא מערך כמובן, והכי חשוב – העובדה שהמערך נמצא בתוך אובייקט לא משנה את זה.

אז מהו הפיתרון?

פשוט מאוד:

let obj1 = {
    'name': 'John',
    'age': 30,
    'food': ['Pizza', 'Salad', 'Burger']
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.food[0] = 'Pasta';
console.log(obj1);
console.log(obj2);

והפלט:

לאחר השימוש ב-JSON.stringify ו-JSON.parse האובייקט שוכפל ללא קשר ל-References.
לאחר השימוש ב-JSON.stringify ו-JSON.parse האובייקט שוכפל ללא קשר ל-References.

על ידי הפיכת האובייקט obj1 למחרוזת באמצעות JSON.stringify ולאחר מכן להחזיר אותו להיות אובייקט באמצעות JSON.parse גורמת לכך שה-References של המערכים "נאבדו" ובכך האובייקט obj2 הוא שכפול מושלם של obj1.

בהצלחה!

נהנת ממאמר זה? הירשם לרשימת התפוצה וקבל עדכונים על מאמרים חדשים!


תגובה אחת בנושא “שכפול אובייקטים ב-JavaScript”

  1. הסבר מצויין בשלבים. הבעיה היא שהפתרון, אמנם עובד אך בביצועים רעים מאד. זה מצויין אם יש מעט אובייקטים קטנים. יאט מאד אם יש הרבה אובייקטים או אובייקטים גדולים. הפתרון האמיתי הוא רקורסיבי.

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *