ECMAScript 6 proxy

המאמר הקודם
המאמר הבא

אחד הפיצ'רים המעניינים ב-ECMAScript 6 הוא פרוקסי. פרוקסי הוא פיצ'ר שפחות מתייחסים אליו בהרבה מדריכים של ES6 כי התמיכה בו היתה עד לא מזמן קלושה למדי, אפילו עם ב-TypeScript\Babel וגם כי הוא קשור למושג האפלולי-משהו Metaprogramming שמשמעותו היא תוכנות שמשתמשות בתוכנות אחרות כקלט שלהן.

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

יש לנו שלושה מונחים שאנחנו צריכים לזכור:

1. target – המטרה. זה האובייקט שאותו אנחנו עוטפים.
2. hanlder – אובייקט שמכיל את הפעולות שאנחנו רוצים לתפוס במטרה – למשל set, get, apply.
3. trap -זו הפעולה. אני אגדיר get trap אם אני רוצה לתפוס את get למשל.

יותר מדי תיאוריה בלי קוד זה לא טוב לבריאות. הנה דוגמת ה-hello world:


var data = {  
  name: 'Billy Bob',
  age: 15
};

var handler = {  
  get(target, key, proxy) { //This is the trap
    const today = new Date();
    console.log(`GET request made for ${key} at ${today}.`);
  }
}

var data = new Proxy(data, handler);

// This will execute our handler, log the request, and set the value of the `name` variable.
var name = data.name;

מה הולך פה? אני מגדיר אובייקט חביב שקוראים לו data. זה האובייקט שאני הולך 'לעטוף'. מייד אחר כך אני יוצא handler שיש בו trap. ה-handler הוא אובייקט פשוט שמכיל את כל ה-traps. במקרה הזה יש לי רק אחד שהוא ה-get. כלומר, כל פעם שמישהו יקרא לאיזושהי תכונה באובייקט המקורי, פונקצית ה-get ב-handler תופעל.

הקשירה עצמה של הפרוקסי נעשית בשורה
var data = new Proxy(data, handler);

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

בוא נדגים את זה עם trap אחר. למשל set שמופעל בכל פעם שמישהו משנה את תכונות האובייקט שלי.


var object = {};

var handler = {  
  set(target, key, value, receiver) { //This is the trap
    console.log(`SET request made for ${key}, value ${value}`);
  }
}

var object = new Proxy(object, handler);

object.someProp = 'Moshe'; //"SET request made for someProp, value Moshe"

כאן אני משתמש ב-trap אחר ולוכד את ה-set. כלומר כל פעם שמישהו ינסה לשנות תכונה כלשהי באובייקט שלי. כל תכונה שהיא – הפרוקסי שלי ידע מזה.

יש לנו לא מעט traps. ראינו עכשיו את get ו-set. כאשר לכל אחד מהם יש ארגומנטים אחרים. יש גם למשל construct, שמופעל בכל פעם שיש לנו new. למשל:


var myFunc = function() {};

var handler = {  
  construct(target, argumentsList, newTarget) { //This is the trap
    console.log('activated!')
    console.log(argumentsList)
  }
}

var myFunc = new Proxy(myFunc, handler);
var whatever = new myFunc('arg1', 'arg2'); //"activated!", ["arg1", "arg2"]

רשימה נאה של כל ה-traps אפשר למצוא כרגיל ב-MDN.

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

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

אהבתם? לא אהבתם? דרגו!

לא אהבתי בכלללא אהבתיבסדראהבתיאהבתי מאוד (10 הצבעות, ממוצע: 4.40 מתוך 5)

תגיות: פורסם בקטגוריה: ECMAScript 6

אל תשארו מאחור! יש עוד מה ללמוד!

הצטרפו לעדכונים!

העדכונים נשלחים אך ורק כאשר האתר מתעדכן.

רן בר-זיק

רן בר-זיקכותב כל המאמרים באינטרנט ישראל, מפתח אינטרנט מנוסה במגוון שפות ופלטפורמות.
ניתן ליצור איתי קשר באמצעות:
כתובת המייל שלי: info@internet-israel.com.
פרופיל הלינקדאין שלי

הטוויטר שלי

פרופיל הפייסבוק שלי

אני תמיד שמח לייעץ ולעזור, אך בשל עומס הפניות הרב, אני לא תמיד מצליח לענות במהירות.