שכפול אובייקטים ב-JavaScript
שכפול של אובייקט ב-JavaScript לא נשמע כמו משהו מסובך במיוחד.
האמת? נכון, זה לא מסובך אבל זה כן טריקי. למה ואיך בפוסט הבא.
נתחיל מהבסיס…
אם ארצה לשכפל אובייקט אוכל לעשות את הדבר הפשוט הבא:
let obj1 = {
'name': 'John',
'age': 30
};
let obj2 = obj1;
console.log(obj1, obj2);
והפלט:

וכמובן שלאחר העתקה ניתן לשנות את ערך של property מסוים, כך:
let obj1 = {
'name': 'John',
'age': 30
};
let obj2 = obj1;
obj1.age = 32;
console.log(obj1);
console.log(obj2);
ובוודאי שזה מה שנקבל בפלט:

רגע..מה?
מדוע 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);
ועכשיו הפלט נראה כך:

ויש אפילו דרך פשוטה יותר…
באמצעות 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 של האובייקט 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);
והפלט:

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