בתכנות, שינוי מצב של אובייקט מתייחס לכך שמצב או נתונים של אובייקט משתנים לאחר יצירתו. במילים אחרות, הפעולה שמשנה את התכונות של אובייקט ב-JavaScript ידועה כשינוי אובייקט. שינוי אובייקט משנה את הערכים של אובייקט ישירות, מה שמקשה, במיוחד ביישומים שבהם מספר פעולות עשויות לנסות לקרוא או לכתוב לאובייקט בו זמנית.
מאמר זה מציע דיון על שינוי אובייקט ב-JavaScript עם דוגמאות קוד רלוונטיות היכן שנדרש.
סוגי נתונים ב-JavaScript
סוגי נתונים מציינים את סוג הנתונים שאפשרות המשתנה או האובייקט יכולים להכיל. JavaScript תומך בשתי קטגוריות שונות של סוגי נתונים: סוגים פרימיטיביים וסוגים שהוגדרו על ידי המשתמש או סוגי הפניה.
סוגי נתונים פרימיטיביים
ב-JavaScript, כל סוגי הנתונים הפרימיטיביים הם בלתי ניתנים לשינוי מטבעם, כלומר, אי אפשר לשנות אותם לאחר שנוצרו. מספרים, בוליאנים, מיתרים, ביגינטס, לא מוגדרים, נולים, סמלים ואובייקטים הם דוגמאות של סוגים פרימיטיביים.
סוגי נתונים שהוגדרו על ידי המשתמש או סוגי נתונים של הפניה
סוגי נתונים שהוגדרו על ידי המשתמש או סוגי נתונים של הפניה הם אובייקטים שנוצרו באמצעות סוגים פרימיטיביים או שילוב של סוגים פרימיטיביים וסוגים שהוגדרו על ידי המשתמש. דוגמאות טיפוסיות של סוגי נתונים שהוגדרו על ידי המשתמש או סוגי נתונים של הפניה הן אובייקטים ומערכים.
איך משתנים מוקצים ומשוייכים מחדש ב-JavaScript
כאשר אתה מבצע השמה של משתנה מסוג פרימיטיבי ל־משתנה מסוג משתנה, שני המשתנים מחזיקים ערכים דומים, אך הם מאוחסנים במיקומי אחסון שונים. לדוגמה, נניח שיש לך שני משתנים varA
ו־varB
ואתה מבצע השמה של אחד מהמשתנים לשני בדרך הבאה:
var varA = 100;
var varB = varA;
console.log(varB);
כאשר אתה מפעיל את קטע הקוד הקודם, המספר 100 יוצג בקונסול. כעת, שינה את הערכים של אחד המשתנים (נניח את varB
) כפי שמוצג כאן.
var varA = 100;
var varB = varA;
varB = 500;
console.log(varA);
שים לב כיצד הערך של המשתנה varB
שונה ל־500. כאשר אתה מדפיס את הערך של varA
, עדיין יוצג 100. זהו מכיוון שהמשתנים varA
ו־varB
מאוחסנים בשני מיקומי זיכרון שונים. לכן, אם תשנה אחד מהם, הערך החדש או המשונה לא ישקף על המשתנים האחרים.
מהו שינוי אובייקט ב־JavaScript?
ב־JavaScript, סוג הנתונים של אובייקט יכול להיות מהשניים: פרימיטיבי או לא פרימיטיבי. בעוד שסוגי הנתונים הפרימיטיביים הם לא ניתנים לשינוי, כלומר, אינך יכול לשנות אותם לאחר שיצרת אותם, ניתן לשנות סוגי לא פרימיטיביים, כלומר, אובייקטים ומערכות. אובייקטים תמיד מאפשרים לשנות את ערכיהם. לכן, ניתן לשנות את מצב השדות עבור סוג משתנה שניתן לשנות בלי ליצור מופע חדש.
שינויים באובייקט עשויים ליצור בעיות רבות, כגון הבאות:
- אובייקטים שעברו שינוי רב עשויים לגרום לתנאי ראס (race conditions) כתוצאה מבעיות עקרונות הזמן המתמשך והבטיחות של תהליכים
- המוטציה יכולה להביא לקושי בקוד המקור עקב בעיות ביטחון צמתים ופחות ניחוש בפעולה
- המוטציה יכולה לגרום לבאגים שיכולים להיות קשים לזהות בקוד המקור של האפליקציה
- המוטציה גורמת לבעיות בבדיקה ותיקון הקוד מאחר שמעקב אחר קוד שמשתמש במוטציה מהווה אתגר
דוגמאות לקוד שמדגימות מוטציה באובייקט
מוטציה באובייקט יכולה לקרות בכל אחת מהמקרים הבאים:
- הוספת, עריכת, או מחיקת פרופרטיס
- שימוש בפעולות שעשויות להציג מוטציה
כאשר אתה משנה פרופרטיס של אובייקט, באופן ישיר או בעקיפין, בגדול אתה מבצע מוטציה לאובייקט. קטע הקוד הבא מראה כיצד ניתן לבצע מוטציה לאובייקט על ידי שינוי הערך המתייחס לפרופרטי id.
const author = { id: 1, name: "Joydip Kanjilal"};
author.id = 2; author.city = "Hyderabad, INDIA";
console.log(author);
בקטע הקוד המוקדם, אנו יוצרים אובייקט בשם author שמכיל שני פרופרטיס, כלומר, id
ו־name
. בזמן שהפרופרטי id משמש לאחסון ה־id של רשומת המחבר, הפרופרטי name מאחסן את שמו של המחבר. שימו לב כיצד אנו מבצעים מוטציה לאובייקט author על ידי שינוי הערך הקשור לפרופרטי id. לאחר מכן, אנו מוסיפים פרופרטי חדש בשם city לאובייקט author ומקצים ערך לפרופרטי זה.
כאשר אתה מפעיל את קטע הקוד המוקדם, הפרופרטים וערכיהם של אובייקט המחבר יוצגו כפי שמוצג למטה:
{ name: 'Joydip Kanjilal', city: 'Hyderabad, INDIA' }
כאשר אתה מעביר אובייקט לפונקציה או משייך אותו למשתנה ב-JavaScript, אתה בעצם מעביר את ההפניה לאובייקט ולא העתק שלו. זה אומר שכל שינוי שתעשה באובייקט החדש שנוצר על ידי העברת אובייקט או שייכותו למשתנה יחול על כל ההפניות של האובייקט האמיתי.
שקול את קטע הקוד הבא שמראה כיצד תוכל ליצור אובייקט ב-JavaScript ולאחר מכן להשאיר אותו למשתנה.
const objA = { id: 1, name: 'Joydip Kanjilal',
city: 'Hyderabad, INDIA', pincode: 500089 }
const objB = objA;
objB.pincode = 500034;
console.log(objA);
בקטע הקודם של הקוד, האובייקט objA
מועבר לobjB
, והערך של מאפיין ה-pincode של objA
משתנה, כלומר, האובייקט objA
משתנה. כאשר תבצע את התוכנית, הנתונים הבאים יוצגו.
{ id: 1, name: 'Joydip Kanjilal', city: 'Hyderabad, INDIA', pincode: 500034 }
שימו לב שהערך של מאפיין ה-pincode שונה.
מניעת שינוי אובייקט ב-JavaScript
ב-JavaScript, אתה יכול למנוע שינוי בכמה דרכים, כגון:
- שימוש בשכפול אובייקט על ידי ניצול מתודת
Object.assign()
או האופרטור המפוזר (…) - שימוש במתודת
Object.seal()
כדי למנוע הוספה או מחיקה של מאפיינים של אובייקט - שימוש במתודת
Object.freeze()
כדי למנוע הוספה, עריכה או מחיקה של מאפיינים של אובייקט
שימוש בשכפול
הפנה לקטע הקוד הבא שמראה כיצד תוכל לשכפל אובייקט ב-JavaScript באמצעות האופרטור המפוזר.
let originalObj = { x: 10, y: 100 }; let clonedObj = { originalObj };
כאן, שם העצם המשובץ הוא clonedObj
, והוא זהה לעצם המקור ששמו originalObj
. לכן, אם תציג את ערכי שתי המאפיינים של שני העצמים הללו, התוצאות תהיינה זהות.
כעת, שנה את ערך אחד המאפיינים של העצם המשובץ ששמו clonedObj
לערך שאתה מעוניין בו, כפי שמוצג בקטע הקוד הבא.
clonedObj.x = 50;
כעת, כתוב את קטע הקוד הבא על מנת להציג את ערך המאפיין ששמו x
הנוגע לשני העצמים originalObj
ו- clonedObj
.
console.log(originalObj.x);
console.log(clonedObj.x);
כאשר תפעיל את התוכנית, תשים לב שערך המאפיין x
בעצם המקור לא השתנה. הערכים יוצגו בקונסול כפי שמוצג למטה:
10
50
משתמשים בשיטת Object.freeze()
שיטת Object.freeze()
יכולה להפוך אובייקט ללא שינוי על ידי מניעת כל שינוי באחד מהמאפיינים שלו.
const author = { id: 1, name: "Joydip Kanjilal",
city: "Hyderabad", state: "Telengana",
country: "India", pincode: 500089};
Object.freeze(author);
author.city = "Bangalore";
author.state = "Karnataka";
author.pincode = 560010;
console.log(author);
כאשר אתה מפעיל את קטע הקוד הקודם, התוצאות תהיינה דומות לכך:
{
id: 1,
name: 'Joydip Kanjilal',
city: 'Hyderabad',
state: 'Telangana',
country: 'India',
pincode: 500089
}
כפי שניתן לראות מהפלט, אף על פי שהוקצו ערכים למאפייני city ו- state, ו- pincode, אין שום השפע. לכן, לא התבצעו שינויים בנתונים שמכילים באחד המאפיינים של האובייקט.
משתמשים בשיטת Object.seal()
באפשרותך גם להשתמש בשיטת Object.seal()
כדי למנוע מוטציה של אובייקט ב-JavaScript. שימוש בשיטה זו יאפשר לך לשנות את ערכי המאפיינים הקיימים, אך לא ניתן לשנות או למחוק אף אחד מהמאפיינים של האובייקט. הדוגמה לקוד הבא ממחישה זאת:
const author = { id: 1, name: "Joydip Kanjilal",
city: "Hyderabad", state: "Telangana",
country: "India", pincode: 500089};
Object.seal(author);
author.city = "Bangalore";
author.state = "Karnataka";
author.pincode = 560005;
author.booksauthored = 3;
console.log(author);
בחתימת הקוד הקודם, תיתכן ששינויים במאפיינים של האובייקט בשם המחבר ייאפשרו, אך לא יתרכזו הוספת או מחיקת המאפיינים של האובייקט. כאשר תפעיל את התוכנית, תראה כי ערכי המאפיינים ששונו משתקפים בתוצאה, אך ההצהרות שמוסיפות או מוחקות מאפיינים מתעלמות. הנה כיצד הפלט ייראה בקונסולה:
{
id: 1,
name: 'Joydip Kanjilal',
city: 'Bangalore',
state: 'Karnataka',
country: 'India',
pincode: 560005
}
שימוש בשיטת Object.defineProperty()
ניתן גם להשתמש בשיטת Object.defineProperty()
ב-JavaScript כדי לשלוט בגמישות של מאפיינים יחידים של אובייקט. הקטע הבא מציג דוגמה כיצד ניתן להשתמש בשיטה זו כדי לאפשר או לאסור שינויים בערך המוכל במאפיין שבו הגמישות מוגבלת.
const author = { id: 1, name: "Joydip Kanjilal"};
Object.defineProperty(author, "booksauthored",
{
value: 3,
writable: false,
});
author.booksauthored = 5;
console.log(author.booksauthored);
כאשר תפעיל את הקטע קוד הקודם, תראה שהמספר 3 מוצג בקונסולה.
נקודות מרכזיות
- JavaScript מסדר את סוגי האובייקטים לשתי קטגוריות שונות: פרימיטיבים (גמישים) ואובייקטים (לא גמישים).
- המונח "תופעת השינוי של אובייקט" מתייחס לפעולות שמשנות או משנות את אובייקט לאחר שנוצר.
- בעוד שערכים פרימיטיביים כמו מספר, וכו ', לא ניתן לשנות אותם, תמיד ניתן לשנות אובייקטים לאחר שנוצרו.
- מאחר שמחרוזות ב-JavaScript הן לא גמישות, אינך יכול לשנות אותן לאחר שנוצרו.
- אף על פי שתופעת השינוי לבדה אינה כזו רעה, עליך לנהל אותה בזהירות כדי להפחית באגים באפליקציות שלך.
- ניתן להפחית או להוריד את תופעת השינויים ב-JavaScript על ידי עקיפת ההמלצות והשימוש במבני נתונים לא גמישים.
Source:
https://dzone.com/articles/an-introduction-to-object-mutation-in-javascript