2016-07-30 51 views
1

背景

過去幾個月我一直在使用OOP風格的Javascript,從解剖開源庫開始。看起來他們大多遵循相同的模式,除了我已經看到了處理私有函數的兩種方法,並且我在想哪個是最好的(最好像最佳實踐一樣,或者因爲我可能不知道的原因而更好)。OOP Javascript:應該將私有函數添加到類原型中嗎?

示例代碼

下面是我正在使用的模式的一個非常簡潔的骨架。如果你會注意到,有兩種不同形式的私人功能。

第一個附屬於原型,如公共功能,但帶有前綴_

第二個只是一個功能,它的範圍只能由該類訪問。

(function(window) { 

    window.FooBarClass = (function() { 

     var Class = function(params) { 

      this._init(params); 

     } 

     /***************************************/ 
     /************* INITIALIZE **************/ 
     /***************************************/ 

     Class.prototype._init = function(params) { 

      // DO SETUP STUFF 

     }; 

     /***************************************/ 
     /********** PUBLIC FUNCTIONS ***********/ 
     /***************************************/ 

     Class.prototype.doThings = function() { 

      // DO STUFF 

     }; 

     /***************************************/ 
     /****** PRIVATE FUNCTIONS 1ST WAY ******/ 
     /***************************************/ 

     Class.prototype._createSection = function(params) { 

      // DO STUFF 

     }; 

     /***************************************/ 
     /****** PRIVATE FUNCTIONS 2ND WAY ******/ 
     /***************************************/ 

     function correctTwoDigitYear(variable) { 

      // DO STUFF 

     } 

     return Class; 

    }()); 

}(window)); 

問題

哪一個是最好的,爲什麼?

+0

'_init'方法幾乎總是一個反模式。只需在構造函數中使用初始化權限即可。 – Bergi

+0

這取決於您是否希望能夠在閉包之外訪問這些方法。 – Oriol

+0

爲什麼使用'_init'是反模式? –

回答

2

第二種模式,將函數放在本地作用域中,因爲它實際上是私有的,所以更好。但它不是真的OOP。

第一種模式是將函數放在原型的下劃線屬性上,因爲它們是實際的方法,它們的默認方式就像您期望的方法那樣傳遞。通過實例化方法,任何需要它們的模塊都可以使用它們,而不受範圍的限制,這對於大型項目可能是有益的。當然,如果你想使用多態性,方法在面向對象方面很重要,因爲它們提供動態調度。

此外,原型方法還有一些更好的優化,所以如果您需要排除性能的最後一點,它們會被選中,儘管在實踐中您不會看到與普通函數調用有很大區別。

+0

我很欣賞這兩種選擇的原因。我現在對這種輕微的性能差異感到好奇,所以當我抽出一些時間時,我會設置jsperf測試。 –

4

JS實際上並沒有私有方法,但正如你所看到的,你可以通過關閉範圍來限制對函數和變量的訪問。最後,如果它在原型上,它不是私有的 - 不管命名約定(主要下劃線等)如何。所以如果你真的想限制訪問的東西,做不是把它放在原型。

+0

感謝您的答覆,非常感謝,upvoted。儘管如此,我將Bergi列爲解決方案,因爲它具有關於我所問的兩個選項的信息,更深入一點。 (希望我可以將這兩個標記爲解決方案)。謝謝你! –

0

附加到函數原型屬性的任何方法均可由對象或子類訪問。 SO,

class.prototype.__init 

不能被視爲私有方法。 它可以由對象是入店或它可以通過擴展類 前進行修改:

var someClass = (function() { 
    var Class = function(params) { 
     this._init(params); 
    } 

    Class.prototype._init = function(params) { 
     console.log("Hello World"); 
    }; 
    return Class; 
}()); 


var extendSomeClass = someClass; 

extendSomeClass.prototype._init = function() { 
    console.log("Hey there"); 
} 

var obj = new extendSomeClass(); // this wil print "Hey there" 

在你已經張貼的例子中,_init充當構造,因此與其相關聯的屬性是公開(儘管命名約定建議私人成員)。但要遵循私人訪問,封閉範圍應該是最佳實踐。 例如:

var fooClass = (function() { 
    var Class = function() { 
    if(this._init) { 
     this._init.apply(this, arguments); 
    } 
    } 


    Class.prototype.hello = function() { 
    log("hello world"); 
    } 

    function log(args) { 
    console.log(args); 
    } 
}()); 

在功能log上面的例子中是一個私有方法,不能被修改/覆蓋範圍之外。

相關問題