• בלוג
  • בואו נכתוב namedtuple ב JavaScript

בואו נכתוב namedtuple ב JavaScript

פוסט זה כולל טיפ קצר בנושא פיתוח Front End. אם אתם רוצים ללמוד יותר לעומק על פיתוח Front End מהבסיס ועד הנושאים המתקדמים תשמחו לשמוע שבניתי קורס וידאו מקיף בנושא זה הכולל מעל 50 שיעורי וידאו והמון תרגול מעשי.
למידע נוסף והצטרפות לקורס בקרו בדף קורס Front End באתר.
 

אחת הפונקציות האהובות עליי בפייתון נקראת namedtuple. היא מייצרת מעין מחלקה עם שדות קבועים, מה שנקרא Data Object. כתיבת משהו דומה ב JavaScript יכולה ללמד אותנו דבר או שניים על השפה.

1. גירסא 1: פשוט קח אוביקט

אז הדבר הראשון שחשבתי עליו כשראיתי את namedtuple זה שבכלל לא צריך את זה ב JavaScript. הנה גירסת פייתון לנקודה:

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(x=10, y=20)

תרגום ישיר ל JavaScript נראה כך:

const p = { x: 10, y: 20 };

וזה עובד. אבל קצת פחות טוב. כי כשנוסיף שדה גירסת הפייתון תכשל ותספר לנו שיש בעיה:

p = Point(x=10, y=20, z=30)
### TypeError: __new__() got an unexpected keyword argument 'z'

אבל JavaScript לא אכפת כי אין הגדרה מפורשת של המבנה.

2. גירסא 2: פשוט תגדיר אוביקט מוקפא

דרך קלה להתגבר על הבעיה הקודמת היא לחתום (seal) את האוביקט:

"use strict";

const p = { x: 10, y: 20 };
Object.seal(p);

p.x = 10;
p.y = 20;

console.dir(p);

p.z = 30;
// TypeError: Cannot add property z, object is not extensible

זה עובד אבל צריך לזכור לקרוא ל seal כל פעם שיוצרים אוביקט. נשים את שתי הקריאות בפונקציה:

"use strict";

function namedtuple(name, data) {
  Object.seal(data);
  return data;
}

const p = namedtuple('Point', { x: 10, y: 20 });
console.dir(p);

p.z = 30;
// TypeError

3. גירסא 3: שיפור המראה בהדפסה

שיפור קטן אחרון לקוד הזה קשור להדפסה. בפייתון כשנדפיס אוביקט מידע כזה נקבל:

Point(x=10, y=20)

נעדכן את פונקציית namedtuple שלנו כדי לקבל תוצאה דומה:

"use strict";

function namedtuple(name, data) {
  const proto = {
    toString() {
      return `${name} ${JSON.stringify(this)}`;
    }
  };

  const obj = Object.create(proto);
  Object.assign(obj, data);
  Object.seal(obj);
  return obj;
}

const p = namedtuple('Point', { x: 10, y: 20 });
console.log(p);

p.x = 30;
console.log(p);

4. היה שווה?

אם חיפשתם דרך לכתוב אוביקטים ב JavaScript בצורה יותר מסודרת - אני לא בטוח שאתם במקום הנכון. כי למרות שזה עובד ברוב המקרים הוספת כל המגבלות שהצגתי כאן רק מסבכת את התוכנית. אני לא מכיר הרבה אנשים שמשתמשים ב seal על אוביקטים. ואולי זה אפילו נחמד שיש לנו את הגמישות.

מצד שני אם למדתם משהו חדש על seal, על Object,create או על Object.assign, או כל טכניקה אחרת שהוצגה פה - אני מרוצה.