הקפאת אובייקט בג'אווהסקריפט

Freeze & Seal בג'אווהסקריפט ואיך הם עוצרים במוטציה על ידי רפרס

במאמר הקודם סיפרתי קצת על מוטציה בג'אווהסקריפט. ואיך בטעות אנו יכולים לשנות אובייקטים. טוב, את זה אנו מכירים – כאשר אני מבצע העתקה ואז שינוי, אובייקט האב משתנה לי. למה? כי אין ממש העתקה, יש reference – התוצאה (נרצה או לא נרצה) נקראת בג'אווהסקריפט מוטציה. הנה דוגמה קצרה רק כדי להזכר:

const object1 = {
  property1: 42
};
const object2 = object1;
object2.property1 = 33;
console.log(object1.property1); // 33 

זה באמת עלול להבעית קצת. אבל ככה השפה עובדת. מצד שני, זה עלול להעיק. פתרון אחד ספציפי הוא תמיד לבצע deep clone (העתקה) או assign כדי לבצע העתקה של האובייקט החדש והמשך עבודה.

const object1 = {
  property1: 42
};
const object2 = Object.assign({}, object1);
object2.property1 = 33;
console.log(object1.property1); // 42 

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

const object1 = {
  property1: 42
};
Object.freeze(object1)
const object2 = object1;
object2.property1 = 33;
console.log(object1.property1); // 42 
console.log(Object.isFrozen(object1)); // true

מה שה-freeze עושה הוא בעצם הקפאת כל התכונות המיידיות של האובייקט. אפשר לבדוק אם אובייקט קפוא באמצעות isFrozen. כדאי לשים לב שאם מדובר באובייקט מורכב (כלומר אובייקט שהתכונה שלו היא אובייקט אחר) – יהיה אפשר לבצע שינוי של האובייקט. בדיוק כמו ב-const.

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


const myArray = ['Value', 'Value2', 'Value3'];

Object.freeze(myArray);

function muteMeBaby(someArray) {
  someArray[0] = 'newValue';
  return someArray;
}

const newArray = muteMeBaby(myArray);
console.log(newArray); // ["newValue", "Value2", "Value3"]
console.log(myArray); // ["newValue", "Value2", "Value3"]

ניסיון של שינוי אובייקט שנמצא ב-freeze יניב שגיאה אם אנו נמצאים ב strict mode.

האמת היא שלא יצא לי לראות יותר מדי שימושים ב-freeze, ולפי דעתי זו טכניקה שאני לא הייתי שמח לראות אותה בקוד שלי מכמה סיבות. אבל ללא ספק טוב לראות וטוב להכיר.

דרך מעניינת נוספת לקבע אובייקטים היא seal. לא, אין הכוונה לזמר האיכותי (האיכותי!) משנות ה-90 אלא לטכניקה שבאמצעותה אני יכול לקבע את התכונות של האובייקט אבל לאפשר לשנות את הערך שלהן.

אני חושב שבמקרה הזה דוגמה טובה יותר מאלף מילים. יצרתי אובייקט ועשיתי לו seal. מהרגע הזה, אני יכול לשנות את התכונות שלו אבל אני לא יכול להוסיף לו חדשות.

const object1 = {
  property1: 42
};
Object.seal(object1)
const object2 = object1;
object2.property1 = 33;
object2.property2 = 11;
console.log(object1.property1); // 33
console.log(object1.property2); // undefined
console.log(Object.isSealed(object1)); // true
console.log(object2.property2); // undefined

See the Pen Seal baby seal by Ran Bar-Zik (@barzik) on CodePen.

זה כמובן עובר לכל האובייקטים שיש להם רפרפנס אליו. זה לא עוצר את כל המוטציות אבל בהחלט יכול לאכוף ממשק. ושוב, זה נחמד מאוד להכיר – אבל אני לא חושב שיש לזה הרבה שימוש. בתכנות מונחה עצמים, הרבה פעמים אנו כן רוצים להתחייב לממשק מסוים. אבל ג'אווהסקריפט היא prototype based וניסיון להכניס לתוכה את ההגיון של ה-class יכול להיות בעייתי. כאמור טוב להכיר, שימושי בכמה מקרים – באופן אישי לא ראיתי שימוש מאוד נרחב.

פוסטים נוספים שכדאי לקרוא

תמונה של עציץ, רספברי פיי ורמקול
רספברי פיי

לגרום לעציץ שלכם לדבר

כך תשתמשו ברספברי פיי, חיישנים וגם בינה מלאכותית שמותקנת על הרספברי פיי (כן) כדי ליצור… עציץ המדבר.

DALL·E 2024-09-06 12.34.24 - A visually engaging post about Python and cryptographic problems. The image should feature a dark-themed background with a glowing, futuristic Python
פתרונות ומאמרים על פיתוח אינטרנט

בעיות במימוש של פונקציות קריפטוגרפיות בפייתון

היום (16 לספטמבר) ממש, אני מעביר הרצאה ב-PyconIL 2024 על בעיות קריפטוגרפיות באפליקציות פייתון. לצערי אי אפשר להכניס את כל הבעיות הקריפטוגרפיות להרצאה אחת או

פתרונות ומאמרים על פיתוח אינטרנט

המנעו מהעלאת source control לשרת פומבי

לא תאמינו כמה אתרים מעלים את ה-source control שלהם לשרת. ככה תמצאו אותם וגם הסבר למה זה רעיון רע.

גלילה לראש העמוד