לאחרונה נוספה לדפדפנים שיטה חדשה לפעולה הדדית שאפשר להפעיל במערכים: Array.prototype.with().
במאמר הזה נסביר איך השיטה הזו פועלת ואיך משתמשים בה כדי לעדכן מערך בלי לשנות את המערך המקורי.
מבוא ל-Array.prototype.with(index, value)
השיטה Array.prototype.with(index, value) מחזירה עותק של המערך שהיא נקראת בו, כשהערך index מוגדר לערך value החדש שסיפקתם.
בדוגמה הבאה מוצג מערך של גילאים. רוצים ליצור עותק חדש של המערך ולשנות את הגיל השני מ-15 ל-16:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
פירוט הקוד:: הפונקציה ages.with(...) מחזירה עותק של המשתנה ages
בלי לשנות את המערך המקורי. ages.with(1, …) מחליף את הפריט השני (index = 1). ages.with(1, 16) מקצה את הפריט השני ל-16.
כך הצלחתם ליצור עותק חדש של המערך עם שינוי.
השיטה הזו שימושית כשרוצים לוודא שהמערך המקורי לא משתנה. במאמר הזה מפורטים כמה תרחישים לדוגמה שבהם כדאי להשתמש בה. אבל בינתיים, כדאי לראות מה היה קורה אם הייתם משתמשים בסימון בסוגריים:
const ages = [10, 15, 20, 25];
const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)
כפי שאפשר לראות, גם המשתנה ages שונה בדוגמה הזו. הסיבה לכך היא שכאשר מקצים את ages = newAges, JavaScript לא מעתיק את המערך אלא יוצר הפניה למערך השני. לכן, כל שינוי באחד מהם ישפיע גם על השני, כי שניהם מצביעים על אותה מערך.
Array.prototype.with() ואי-שינוי
אי-שינוי הוא הבסיס של הרבה ספריות ומסגרות עבודה של frontend, למשל: React (ו-Redux) ו-Vue
בנוסף, ספריות ומסגרות אחרות לא בהכרח דורשות אי-שינוי, אבל מעודדות אותו לשיפור הביצועים: Angular ו-Lit
לכן, מפתחים נאלצו לעיתים קרובות להשתמש בשיטות אחרות שהחזירו עותקים של מערכים, מה שפגע בקריאות הקוד:
const ages = [10, 15, 20, 25];
const newAges = ages.map((age, index) => {
if (index === 1) {
return 16;
}
return age;
});
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)
הנה דוגמה ב-Codepen לשימוש ב-.with() ב-React בשילוב עם useState כדי לעדכן באופן בלתי משתנה מערך של פריטים:
מכיוון שהשיטה .with() מחזירה עותק של המערך, אפשר לשרשר כמה קריאות של .with() או אפילו שיטות אחרות של מערכים. בדוגמה הבאה מוצגות שתי דרכים להגדלת הגיל השני והשלישי במערך:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)
console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
שיטות חדשות נוספות שאי אפשר לשנות
לאחרונה נוספו שלוש שיטות נוספות שניתן להשתמש בהן לסירוגין:
-
Array.prototype.toReversed()שמחזירה את המערך הפוך בלי לשנות את המערך המקורי. -
Array.prototype.toSorted()שממיין את המערך בלי לשנות את המערך המקורי. -
Array.prototype.toSpliced()שפועלת כמו .splice()אבל בלי לשנות את המערך המקורי.
לפי MDN, שלוש השיטות האלה הן גרסת ההעתקה של השיטות המקבילות. אפשר להשתמש בשיטות האלה גם במקרים שבהם נדרשת או מועדפת אי-שינוי.
לסיכום, אפשר לבצע עדכונים בלתי ניתנים לשינוי בקלות רבה יותר ב-JavaScript באמצעות אחת מארבע השיטות שמוצגות במאמר הזה. במילים אחרות, השיטה .with() מאפשרת לעדכן בקלות רכיב יחיד במערך בלי לשנות את המערך המקורי.