2012-04-08 50 views
2

我有這樣的代碼在這裏:使用Javascript的私人會員。它們可以是非靜態的嗎?

var Person = (function() { 
    var name; 

    var PersonConstructor = function(n) { 
     name = n; 
    }; 

    PersonConstructor.prototype.getName = function() { 
     return name; 
    }; 

    return PersonConstructor; 

})(); 

var people = []; 
var person1 = new Person("Foo"); 
var person2 = new Person("Bar"); 
alert(person1.getName()); // I want it to be Foo 
people.push(person1); 
people.push(person2); 

我從here.模擬類的想法。但是當然,我忽略了私有變量var name;也是一個靜態變量的事實。既然這是絆倒我目前的努力,我想知道在這個例子中是否有辦法保持私人行爲,但避免靜態的?

+1

您不能在構造函數中引用原型函數引用局部變量。我會遠離在JavaScript中模擬可見性的方式。這不僅僅是語言的一部分,還會產生更多的問題。使用適當的文檔,將屬性標記爲'@ private',並根據代碼的用例,使用像Google的Closure編譯器這樣的東西,只按照他們的實際名稱公開屬性。 – 2012-04-08 12:06:10

回答

0

使用原型時沒有「私有」。

應該指出,私人國家沒有價值,避免它像瘟疫一樣。封閉是醜陋和昂貴的。

var o = { 
    name: value 
} 

但是如果你堅持是妄想和希望私有狀態不好則

你可以在一個封閉

function nameHolder(name) { 
    return { 
     get name() { 
      return name 
     }, 
     set name(n) { 
      name = n 
     } 
    } 
} 

注意,這是非常低效的,有小的好處存儲狀態。

或者,你可以存儲在一個weakmap狀態

function privates() { 
    var map = new WeakMap() 

    return function (key) { 
     var v = map.get(key) 
     if (!v) { 
      v = {} 
      map.set(key, v) 
     } 
     return v 
    } 
} 

var NameHolder = (function() { 
    var state = privates() 

    return { 
     constructor: function (name) { 
      state(this).name = name 
     }, 
     getName: function() { 
      return state(this).name 
     } 
    } 
}()) 

WeakMap瀏覽器的支持是不存在的,從而使用pd.Name

+0

你能詳細解釋一下嗎?所以對於我想要保持「私密」的每個變量(抱歉不知道如何反駁),我必須創建一個持有者函數?編輯:好吧,我看到你的闡述,我會嘗試這一點,雖然我必須試着讓我的頭在它周圍。 – gmunk 2012-04-08 12:02:27

+3

我很驚訝@Raynos沒有更私人的國家使用更積極。這是一個足夠公平的問題,但問問自己,你真的需要私人國家嗎?你可以遵循這樣的慣例,用一個前導的下劃線來標​​記你所有的內部不被混淆的變量。可能更容易調試,效率更高。 – 2012-04-08 12:06:11

+1

你聲稱封閉是醜陋和昂貴的。確實,跨越範圍邊界以進行參考查找需要花費,但是編寫良好的代碼可以將代價降到最低,並且在現代JIT解釋器中,它通常在循環之外是無關緊要的。關閉可能是JavaScript中最優雅和表達的功能。關閉是使2000行的等價Java程序在JavaScript中只有500行的原因。 – austincheney 2012-04-08 13:25:12

2

使用this

var Person = (function() { 
    var PersonConstructor = function(n) { 
    this.name = n; 
    }; 

    PersonConstructor.prototype.getName = function() { 
    return this.name; 
    }; 

    return PersonConstructor;  
})(); 

不幸的是,這不會保留私人狀態。

+0

這不保留名稱的「私人」狀態? – 2012-04-08 11:56:28

+0

是的,沒錯。忘了它。 – Alexander 2012-04-08 11:58:21

+0

這是行不通的,但據說它不保留所謂的私人狀態,也許我應該堅持命名約定。 – gmunk 2012-04-08 11:59:55

1

這只是一個範圍問題效仿。

var Person = (function(){ 

    var PersonConstructor = function(n){ 
     // *************************************************************** 
     // PRIVATE VARIABLES AND FUNCTIONS 
     // ONLY PRIVELEGED METHODS MAY VIEW/EDIT/INVOKE 
     // *************************************************************** 

     var myName=n?n:"John Doe"; 

     // *************************************************************** 
     // PRIVILEGED METHODS 
     // MAY BE INVOKED PUBLICLY AND MAY ACCESS PRIVATE ITEMS 
     // MAY NOT BE CHANGED; MAY BE REPLACED WITH PUBLIC FLAVORS 
     // *************************************************************** 
     this.toString=this.getName=function(){ return myName } 
    } 
    return PersonConstructor; 
})(); 

var person1 = new Person("foo"); 
var person2 = new Person("bar"); 

alert(person1.getName()); 
alert(person1.toString()); 
alert(person1.myName); 

// alerts "foo", "foo", undefined 

編輯 - 這是我的原始解決方案。

var Person = function(n){ 
    // *************************************************************** 
    // PRIVATE VARIABLES AND FUNCTIONS 
    // ONLY PRIVELEGED METHODS MAY VIEW/EDIT/INVOKE 
    // *************************************************************** 

    var myName=n?n:"John Doe"; 

    // *************************************************************** 
    // PRIVILEGED METHODS 
    // MAY BE INVOKED PUBLICLY AND MAY ACCESS PRIVATE ITEMS 
    // MAY NOT BE CHANGED; MAY BE REPLACED WITH PUBLIC FLAVORS 
    // *************************************************************** 
    this.toString=this.getName=function(){ return myName } 

} 

var person1 = new Person("foo"); 
var person2 = new Person("bar"); 

alert(person1.getName()); 
alert(person1.toString()); 
alert(person1.myName); 

// alerts "foo", "foo", undefined 
+0

特權方法和公共方法不能很好地協同工作。 – Raynos 2012-04-08 13:25:59

+0

@Raynos - 對我來說似乎很好。就個人而言,我會取消prototype.getName,但它是OP設計的一部分,所以我想我會把它留在那裏。 – 2012-04-08 13:27:05

+0

您的特定示例將更適合公共只讀屬性。在真實世界的情況下,這是行不通的 – Raynos 2012-04-08 13:28:52

相關問題