簡體   English   中英

使用類似於C ++ class-private的隱私和原型(模板)創建對象

[英]Creating an object with privacy and prototyping(templating) similar to C++ class-private

**編輯 - 這在答案中沒有明確說明......但是你不能擁有“模板化(即不為每個實例復制)”的私有成員而沒有自動執行功能。 您將支付處理器時間和代碼復雜性以保護隱私

像C ++私有類成員一樣。

我一直在努力確定什么樣的“hack”用於創建類似乎有超過10種人們定義類的方式。

我正在尋找的類的類型提供隱私和模塊化以及模板機制。 Javascript有原型來創建這個模板機制。 但是我目前使用的解決方案沒有私人成員。

如果沒有,我不得不問這個問題,如果我將所有的javascript移動到這個類類型,那么成本是多少...其中每個都是自執行函數? 現在,當我的代碼加載它時,必須先運行它才能使用它。

這個成本是更好的編程實踐的折衷。 現在我有適當的隱私課程。

成本值得嗎? 額外的運行時間值得隱私嗎?

以下是一些類似的問題:

目前的方法 - 缺乏隱私......散布出來...... 不包括在parantheses中

var Message = function( div ) 
{
    this.div = document.getElementById( div ); 
};

Message.prototype.messages = 
{ 
    name:       'Please enter a valid name',
    email:      'Please enter a valid email',
    pass:       'Please enter passoword, 6-40 characters',
    url:        'Pleae enter a valid url',
    title:      'Pleae enter a valid title',
    tweet:      'Please enter a valid tweet',
    empty:      'Please complete all fields',
    same:       'Please make emails equal',
    taken:      'Sorry, that email is taken',
    validate:   'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
};

Message.prototype.display = function( type ) 
{
    Control.sendInner( this.div, this.messages[type] );
};

Javascript有原型來創建這個模板機制。 但是我目前使用的解決方案沒有私人成員。

我所知道的使用原型和私有狀態的唯一機制是WeakMaps。

這基本上涉及在原型范圍內具有本地WeakMap

免責聲明: WeakMaps是ES6 ,我相信目前只有firefox 6有一個實現 ,但是它們可以是shimmed

var Message = (function() {
    var map = new WeakMap();

    var Message = function(div) {
        var privates = {};
        map.set(this, privates);
        privates.div = document.getElementById(div);
    };

    Message.prototype.messages = {
        name: 'Please enter a valid name',
        email: 'Please enter a valid email',
        pass: 'Please enter passoword, 6-40 characters',
        url: 'Pleae enter a valid url',
        title: 'Pleae enter a valid title',
        tweet: 'Please enter a valid tweet',
        empty: 'Please complete all fields',
        same: 'Please make emails equal',
        taken: 'Sorry, that email is taken',
        validate: 'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
    };

    Message.prototype.display = function(type) {
        var privates = map.get(this);
        Control.sendInner(privates.div, this.messages[type]);
    };

    return Message;
}());

需要注意的是WeakMaps是ES6,並且有一個顯著的計算開銷從weakmap獲取對象,而再從this

我有一篇關於模仿WeakMaps的文章 - 原型和私有狀態

使用文章中提到的klass實用程序,代碼如下所示:

var Message = klass(function(privates) {
    return {
        constructor: function(div) {
            privates(this).div = document.getElementById(div);
        },
        messages: {
            name: 'Please enter a valid name',
            email: 'Please enter a valid email',
            pass: 'Please enter passoword, 6-40 characters',
            url: 'Pleae enter a valid url',
            title: 'Pleae enter a valid title',
            tweet: 'Please enter a valid tweet',
            empty: 'Please complete all fields',
            same: 'Please make emails equal',
            taken: 'Sorry, that email is taken',
            validate: 'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
        },
        display = function(type) {
            Control.sendInner(privates(this).div, this.messages[type]);
        }
    };
});

再次使用privates(this).x而不是this.x具有兩個函數調用的計算開銷。 這不應該被忽視。

還要注意,使用weakmaps比使用閉包具有更少的內存開銷,因為你仍然使用原型進行函數並且只使用弱映射進行狀態。

成本值得嗎? 額外的運行時間值得隱私嗎?

就個人而言,我說“隱私”的運行時間懲罰是需要進行基准測試的。 計算開銷很小,內存使用開銷也很小。

所以,我使用的形式是這樣的:

var Message = function (div) {
    this.div = document.getElementById(div);
    // messages will be 'private'
    var messages = { 'name' : 'Please enter ...' }; // You get the picture here

    this.display = function (type) {
        Control.sendInner(this.div, messages);
    }
}

您可以在對象范圍標題下的這篇文章中閱讀有關私有,靜態和公共變量的更多信息。

更新:您還可以使用嚴格模式並設置不可寫變量或僅限getter值。 盡管如此,您可能希望這不受支持,並且可能會使您在編寫代碼方面更加嚴格。

在您的構造函數中,您該函數中聲明的任何變量實際上都是私有的 - 它僅限於該實例,即:

var Message = function( div ) 
{
    var private = "hello, world!";
    this.div = document.getElementById( div ); 
};

但是,這些變量非常私密,無法從您隨后添加到原型的函數中訪問它們。

訪問它們的唯一方法是通過所謂的“特權法”,作為財產造成即那些this對象內部

除非通過使用變量的范圍規則,否則我認為JavaScript中不存在任何隱私。 但這並不總是意味着立即調用的函數表達式。 您可以使用構造函數范圍的變量與構造函數分配的方法相結合,如下所示:

function YourConstructor() {
    var private1 = 0,
        private2 = 'spock';

    this.count = function () { return private1++; }    
    this.chiefOfficer = function (name) { 
       if(name) private2 = name;
       return private2; 
    }
}

即使你在定義YourConstructor之前執行代碼, YourConstructor發生前向聲明魔術並且一切都很好( 注意 :發布的其他一些解決方案使用var YourConstructor = function () {... idiom - 這些都行不通在需要前方聲明的情況下)。

這有一個問題:每次調用構造函數時,都要定義構造函數指定的方法(而不是一次分配給原型)。 在您創建大量這些對象的情況下,可能會有性能/內存命中。

但是,關於隱私的一句話:我邀請您考慮一下這樣的觀點,即大多數時候,通過運行時強制機制對隱私的需求被高估了。

為什么? 開發人員有很多事情要做; 在所有的可能性,他們很可能寧可不要注意任何給定的抽象的內部,除非它泄漏有毒的東西。

不會導致問題的類,拋出/返回有用的錯誤,提供真正有用的方法,你可以調用它來完成任務(對很多getter和setter!),並且記錄得很好......這些類可能不會需要任何類型的隱私執行機制,因為每個人都會對你的課程拯救他們的工作感到高興,他們不會在里面同行。

對於不符合該標准的類,缺乏隱私執行機制可能不是真正的問題。

有一個例外:有時候(特別是在可以通過網絡瀏覽的網頁上),您可以使用不受信任的來源與您的代碼混合。 在一種非常動態的語言(如JavaScript)中,您可能希望在外部代碼無法訪問的地方隔離/隱藏某些功能。 但是,如果您不擔心這一點,您可能希望花更多時間通過良好的設計和文檔來鼓勵實施隱藏/隱私,而不必擔心技術執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM