簡體   English   中英

使用閉包還是常規構造函數來創建私有屬性?

[英]Closure versus regular constructor function for creating private properties?

我聽說閉包的優點之一是可以為對象創建私有屬性,如下所示。

function Func2(){
    //A is a closure, kept alive after the Func2 has returned, 
    //After Func2 returns, A is only accessible by getA and setA (it's "private")
    var A = 100;
    return {
        getA: function(){
            return A;
        },
        setA: function(newA){
            A = newA;
        }
    }
}

您可以使用getter和setter函數獲取並設置使用Func2創建的對象的私有屬性A ...

var obj2 = Func2();
obj2.getA();
obj2.setA(200);

但是,如果我可以使用常規構造函數執行相同的操作,那有什么意義呢?

function Func1(){ 
    var A = 100; //A is a private property of any object created with the Func1 constructor
    this.getA = function(){
            return A;
            };
    this.setA = function(newA){
        A = newA;
    };
}

訪問私有屬性的方法相同。

var obj1 = new Func1()
obj1.getA();
obj1.setA(200);

正如其他人在評論中指出的那樣,在兩種情況下都將創建一個閉包,並且兩者都將起作用。

我認為建議對模塊模式使用return方法的原因是,該模塊模式不使用Javascript的原型鏈,因此沒有必要使用會創建新原型的常規構造函數(這是不必要的,會浪費內存)。 在您的示例中,由Func2創建的對象將僅具有默認的Object.prototype原型,而由Func1創建的對象將具有Func1.prototype的原型,而該原型又具有Object.prototype的原型。 另外, Func2的優點是可以使用new關鍵字,也可以不使用new關鍵字(盡管由於上述原因,如果您使用模塊模式,最好避免使用new關鍵字)。 (我已經看到一些程序員抱怨這樣一個事實,即如果程序員忘記了傳統的OO Javascript中的new關鍵字,它會導致難以檢測的錯誤;不過我個人從來沒有發現這是一個問題)。

您可能已經知道,私有變量的另一種方法是簡單地在它們前面加上_ ,例如:

function Func1() { 
    this._A = 100;
}

Func1.prototype = {
    constructor: Func1,

    getA: function(){
        return this._A;
    },

    setA: function(newA){
        this._A = newA;
    }
};

我個人更喜歡這種方式而不是模塊模式-私有變量的主要目標是與其他程序員進行通訊,即“這是一個內部屬性;不要直接訪問它”-下划線前綴是眾所周知的約定。 私有屬性從來沒有真正地100%阻止訪問那些屬性,只是阻止了它(考慮一下,大多數編程語言都允許您使用反射來訪問私有屬性這一事實)。 而且,只需在下划線加上前綴即可讓您輕松擁有除私有屬性(對子類型/子類有用)之外的“受保護”屬性。 利用原型鏈還可以提高內存效率,因為每個實例沒有相同功能的多個副本。

但是我確實意識到,盡管下划線命名約定很簡單,但是某些程序員仍然喜歡使用模塊模式來真正使私有屬性無法從閉包外部訪問。 如果您想這樣做,那么我建議您使用傳統的模塊模式,如第一個示例所示,使用return語句。

如果您更喜歡使用模塊模式,但仍然想聲明公共屬性(而不是在最后的return語句中),則可以考慮的另一種模式是創建一個新對象,並使用它代替this ,例如:

function Func3(){ 
    var obj = {};
    var A = 100;
    obj.getA = function(){
        return A;
    };
    obj.setA = function(newA){
        A = newA;
    };
    return obj;
}

(順便說一句,對於私有方法 ,相對於私有數據屬性,即使您使用原型方法,下划線前綴也不是必需的。 此答案中的代碼示例就是一個示例。)

暫無
暫無

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

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