איברים פרטיים ב-Javascript

Private Members in JavaScript

Douglas Crockford

אובייקטים

ביסודו, Javascript הוא כולו בנוגע לאובייקטים. מערכים הינם אובייקטים, פונקציות הינם אובייקטים, אובייקטים הינם אובייקטים וכן הלאה. אם כן, מהם למעשה אובייקטים? אובייקטים הינם אוסף זוגות זוגות של שם וערך. השמות הינם מחרוזות והערכים הינם מחרוזות, מספרים, בוליאנים ואובייקטים (כולל מערכים ופונקציות). אובייקטים מיושמים ברוב המקרים כ-Hashtables, כך שניתן לשלוף ערכים במהירות.

אם הערך הינו פונקציה, אנו יכולים להתייחס אליו כאל שיטה. (Method). כאשר שיטה של אובייקט מופעלת, המשתנה this מוקצה לאובייקט. ואז השיטה (method) יכולה לגשת למשתנים דרך המשתנה this.

אובייקטים יכולים להווצר ע"י "בנאים" (constractors), שהם פונקציות אשר מאתחלות אובייקטים. בנאים מספקים תכונות ש-classes מספקים בשפות אחרות, כולל משתנים סטטיים ושיטות.

ציבורי (Public)

האיברים של אובייקט, כולם איברים "ציבוריים" (Public). כל פונקציה יכולה לגשת, לשנות, למחוק את האיברים האלו או להוסיף איברים נוספים. ישנן שני דרכים ראשיות להצבת איברים באובייקט חדש.

בתוך הבנאי:

משתמשים בטכניקה זו בד"כ כדי לאתחל משתנים ציבוריים. המשתנה this של הבנאי משמש להוספת איברים לאובייקט

function Container(param){ 	
    this.member = param;     
}  

כך, שאם אנו בונים אובייקט חדש

var myContainer = new Container('abc'); 		

אז myContainer.member יכיל 'abc'.

בתוך האב-טיפוס (Prototype):

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

Container.prototype.stamp = function (string) { 	
    return this.member + string; 
}

כך, אנו יכולים להפעיל את השיטה

myContainer.stamp('def')

אשר מפיקה 'abcdef'.

פרטי (Private)

איברים פרטיים מיוצרים ע"י הבנאי. באופן כללי var-ים ופרמטרים של הבנאי הופכים לאיברים פרטיים.

function Container(param) { 	
this.member = param;
var secret = 3;
var self = this;
}

הבנאי הזה יוצר שלושה משתנים פרטיים: param, secret ו-self. הם מוצמדים לאובייקט, אך הם אינם נגישים מחוץ לאובייקט, הם גם לא נגישים לשיטה הציבורית של האובייקט. הם כן נגישים לשיטות פרטיות. שיטות פרטיות הינן פונקציות פנימיות של הבנאי.

function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
}else {
return false;
}
}
this.member = param;
var secret = 3; var self = this;
}

השיטה הפרטית dec בודקת את המשתנה secret. אם הוא גדול מ-0, הוא מפחית את ערכו ומחזיר true. אחרת הוא מחזיר false. אפשר להשתמש בו כדי להפוך את אובייקט זה מוגבל לשלושה שימושים.

כנוהג, אנו יוצרים פרמטר self פרטי בו משתמשים כדי להפוך את האובייקט זמין לשיטה הפרטית. זהו מעקף (Workaround) של שגיאה בהגדרות שפת ECMAScript אשר גורמת ל-this להיות מוגדר לא נכון עבור פונקציות פנימיות.

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

מיוחס (Privileged)

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

שיטות מיוחסות מוקצות בעזרת this בתוך הבנאי.

function Container(param) {

    function dec() {
        if (secret > 0) {
            secret -= 1;
            return true;
        } else {
            return false;
        }
    }

    this.member = param;
    var secret = 3;
    var that = this;

    this.service = function () {
        if (dec()) {
            return that.member;
        } else {
            return null;
        }
    };
}

service הינה שיטה מיוחסת. קריאה ל-myContainer.service() תחזיר 'abc' בשלושת הפעמים הראשונות שהיא תקרא. לאחר מכן, היא תחזיר null. service זמין לאובייקטים ושיטות אחרות, אך אינה מאפשרת גישה ישירה לאיברים הפרטיים.

סגירות (Closures)

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

איברים פרטיים ומיוחסים יכולים להווצר רק כאשר אובייקט נמנה. איברים ציבוריים יכולים להתווסף בכל זמן נתון.

דוגמאות

ציבורי (Public)

function Constructor(...) {
this.membername = value; } Constructor.prototype.membername = value;

פרטי (Private)

function Constructor(...){
var self = this;
var membername = value;
function membername(...) {
...
}
} // Note: The function statement function membername(...) { ... }
// is shorthand for var membername = function membername(...) { ... };

מיוחס (Privileged)

function Constructor(...) {
this.membername = function (...) {
...
};
}

Copyright 2001 Douglas Crockford. All Rights Reserved Worldwide.