2013-04-06 55 views
0

我希望使用https://github.com/mozilla/BrowserQuest/blob/master/server/js/lib/class.js具有私有可繼承的屬性,還有一些getters和setter在那裏。如何設置一個JavaScript繼承+私有屬性+ getters/setters

基本上我想讓getter/setter修改私有屬性和子類來繼承setter,getter和private屬性當然。 這是我走到這一步:

var Person = Class.extend({ 
    init: function(name) 
    { 
     var name = "~"; 

     this.myName = name; 

     return { 
      set myName(value) 
      { 
       name = value + " +?"; 
      }, 
      get myName() 
      { 
       return name + "^^^^^^^^^"; 
      } 
     } 
    } 
}); 
var c = new Person("cheese"); 
console.log(c.myName); 
c.myName = "zoom"; 
console.log(c.myName); 

跟蹤: 未定義 變焦

它的怪異,我的編輯器(Webstorm)認爲c.myName作爲二傳手/吸氣但是編譯器認爲這是一個未定義公共財產:(

任何幫助,將不勝感激。這是但的NodeJS我認爲問題是JavaScript的。

+0

你在哪裏執行此JavaScript? – 2013-04-06 15:28:40

回答

4

我假設的Node.js或任何其他環境中,整個EcmaScript 5可用。

如今在JavaScript中擁有真正的私有數據的唯一方法是在構造函數中保存一個變量,這就是你正在做的事情。但是,您在init函數中使用return會令人困惑。儘管init函數幾乎是構造函數,但它並沒有像這樣被調用,所以return什麼都不做。即使它做了什麼,你想要的是添加一個屬性到this,而不是返回一個新的對象。所以基本上你不得不改變returnObject.defineProperty

init: function (name) { 
    // notice that the private variable has a different name 
    // than the parameter 
    var privateName = '~'; 

    Object.defineProperty(this, 'myName', { 
    set: function (value) { 
     privateName = value + " +?"; 
    }, 
    get: function() { 
     return privateName + "^^^^^^^^^"; 
    } 
    }); 

    this.myName = name; 
} 

這仍然在繼承的限制。如果您想從Person類繼承並修改getter和setter,則必須獲取屬性描述符,然後對其進行修改並重新定義屬性。這很痛苦。它不支持訪問「超級getter/setter」。爲了避免我們通常在JavaScript中執行的操作是忘記擁有真正的私人用戶,並按慣例使用私人用戶,請使用_開始私有用戶的名稱。然後,你可以簡單地定義你的getter和setter原型是這樣的:

var Person = Class.extend({ 
    init: function(name) { 
    // the private name property 
    this._name = '~'; 

    this.myName = name; 
    }, 
    set myName(value) { 
    this._name = value + " +?"; 
    }, 
    get myName() { 
    return this._name + "^^^^^^^^^"; 
    } 
}); 

這將讓你使用繼承訪問時超的getter/setter。

有一個先進的功能,可以讓你有真正的私人和繼承獲取和設置:WeakMap。 WeakMap基本上是一個對象,它創建了另外兩個對象之間的關係,這些對象不計入垃圾回收。最後一部分對於內存管理很重要,第一部分是讓你擁有真正私有化的部分。您可以使用--harmony_collections標誌嘗試Firefox的Beta版本和Node.js中的WeakMaps。這是如何工作的:

function privatize() { 
    var map = new WeakMap(); 
    return function (obj) { 
    var data = map.get(obj); 
    if (!data) { 
     map.set(obj, data = {}); 
    } 
    return data; 
    }; 
} 

var Person = (function() { 
    var _private = privatize(); 

    return Class.extend({ 
    init: function(name) { 
     // the private name property 
     _private(this).name = '~'; 

     this.myName = name; 
    }, 
    set myName(value) { 
     _private(this).name = value + " +?"; 
    }, 
    get myName() { 
     return _private(this).name + "^^^^^^^^^"; 
    } 
    }); 
}()); 
+0

你先生,應該有一個裝滿啤酒的浴缸。很好的答案,消化所有這一切將需要相當多的時間。我正在使用節點js並在Webstorm中進行編輯。您是否在說_name屬性是公開的,我可以訪問,但是應該將它編碼爲從未存在過? – Discipol 2013-04-06 19:05:54

+0

是的,這就是我們大多數人的做法:按照約定同意以'_'開頭的屬性是私有的。在語言演變之前,它是性能(原型更快,內存更高效)和封裝之間的折衷。但另一方面,暴露私有有助於調試。 – juandopazo 2013-04-07 22:48:22