מכירים את X-men? טוב, זה לא X-men אבל בג׳אווהסקריפט, בגלל שהיא prototype based (ולא, לא מונחית עצמים) יש חשיבות גדולה למוטציות. ובשפת גויי הים: MUTABLE VS IMMUTABLE. מה זה אומר? זה אומר אובייקט שניתן לשנות אותו או אובייקט שלא ניתן לשנות אותו. כאשר אנו משתמשים בכל סוג אובייקט כזה בהתאם לצרכים שלנו.
על מנת להדגים, אני אראה לכם קוד שמבצע מוטציה. שימו לב:
const myArray = ['Value1', 'Value2', 'Value3'];
function muteMeBaby(someArray) {
someArray[0] = 'newValue';
return someArray;
}
const newArray = muteMeBaby(myArray);
console.log(newArray); // ["newValue", "Value2", "Value3"]
console.log(myArray); // ["newValue", "Value2", "Value3"]
יש לנו כאן פונקציה פשוטה שמקבלת מערך ומשנה את האיבר הראשון. זה הכל. בסיום הפונקציה היא מחזירה את המערך שהיא קיבלה. פשוט ביותר, לא?
אני יוצר מערך בשם myArray ומעביר אותו דרך הפונקציה. מה שהפונקציה מחזירה נכנס לתוך מערך שני בשם newArray. זה לא מפתיע ש-newArray מכיל את הערך החדש באיבר הראשון. הוא עבר דרך הפונקציה וזה מה שאני מצפה שיקרה. מה שאני פחות מצפה שיקרה הוא שהמערך הראשון myArray ישתנה. אבל למה הוא משתנה? למה הוא משתנה למען השם?!? זה מה שמטריף מתכנתי ג׳אווהסקריפט מתחילים.
See the Pen mute me baby one more time by Ran Bar-Zik (@barzik) on CodePen.
הפונקציה הזו מבצעת מוטציה במערך המקורי. כיוון שמה שנכנס לתוכה זה לא עותק של מערך חדש אלא רפרנס למערך הישן וכל שינוי ברפרנס הזה משפיע על המערך הישן. הארגומנט someArray שנמצא בפונקציה לא יוצר מערך חדש אלא בעצם מכיל רפרנס למערך הקיים.
זה לפעמים מצב רצוי ולפעמים מצב לא רצוי. איך מונעים אותו? מנתקים את הקשר בין הארגומנט והמערך שנמצא בתוך הפונקציה למערך המקורי. עושים את זה על ידי משהו שנקרא שיבוט או clone. במקרה של מערך פשוט אפשר לעשות את זה עם destructuring שכתבתי עליו בעבר. בגדול זה לפרק את המערך ולהרכיבו מחדש אבל תוך כדי שאני מבצע העתקה. העתקה ולא הפניה (רפרנס) :
const myArray = ['Value1', 'Value2', 'Value3'];
function muteMeBaby(someArray) {
const innerArray = [...someArray]; // This is clone
innerArray[0] = 'newValue';
return innerArray;
}
const newArray = muteMeBaby(myArray);
console.log(newArray); // ["newValue", "Value2", "Value3"]
console.log(myArray); // ["Value1", "Value2", "Value3"]
יש כמעט בכל ספריה דרכים לבצע clone. וצריך לשים לב היטב לעניין הזה של המוטציה. כי אם אנחנו לא עוצרים את המוטציה, ייתכן שיהיו לנו בעיות במידע שלנו. זה פיצ׳ר מאוד בסיסי של ג׳אווהסקריפט – אבל אפשר לצלוח קריירה שלמה בלי להכיר אותו לעומק.
See the Pen No mute for you! come back one year! by Ran Bar-Zik (@barzik) on CodePen.
הוא כמובן קיים גם באובייקטים ולא רק במערכים.
4 תגובות
אני לא מבין מה הקשר לmutations במאמר הזה
זה ניראה כאילו אתה מדבר פשוט על העברת reference
אין פה דיבור בכלל על immutables
מרגיש טיפה כאילו הכותרת לא הכי מדויקת…
אתה צודק לחלוטין הכותרת מגוחכת
זה לא העברת reference זה פשוט בניה של מערך חדש לאחר באמצעות האופרטור spread
מציעה להתייחס גם למצבים בהם יש לך nested objects/arrays בתוך המערך המקורי ואיך מתמודדים עם זה