2011-04-20 61 views
11

getter和setter方法是一個美女在VB.Net:__defineGetter__的替代方案?

Get 
    Return width 
End Get 
Set(ByVal value As Integer) 
    width = value 
End Set 

在Javascript中,這可能是我們會怎樣做:

function Test() { 
    var width = 100; 
    this.__defineGetter__("Width", function() { 
     return width; 
    }); 
    this.__defineSetter__("Width", function(value){ 
     width = value; 
    }); 
} 

它看起來像被洗劫庫裏的意大利麪條一盤。我們有什麼更好的選擇?

注意:新代碼應該使用new Test().Width訪問值,而不是new Test().Width()

+0

順便說一句,我需要一個「吸」,因爲不是**返回; **我們可以假設像** f();返回一個; ** – Pacerier 2011-04-20 13:54:22

+4

這個問題和以前的問題有什麼不同? http://stackoverflow.com/questions/5731039/private-variables-in-object-literals – Chandu 2011-04-20 13:54:44

+0

根據你的其他問題,是不是「a」應該由「測試」的所有實例共享? – Alnitak 2011-04-20 14:09:29

回答

11

隨着ES5你就可以做到:

function Test() { 
    var a = 1; 

    return { 
    get A() { return a; }, 
    set A(v) { a = v; } 
    }; 
} 

的的getter/setter功能當然可以做你想讓他們任何東西。

+1

這使得記憶力增加,因爲每個物體的吸氣和吸氣都是「獨特的」。此外,在構造函數中返回表達式時,您無法真正對原型進行任何操作。 – 2012-01-03 10:19:00

+0

@TylerCrompton是的,這絕對是真的;我只是按照原始問題的提綱。如果可能,最好讓原型上的getter/setter。 – Pointy 2012-01-03 19:50:07

+3

可以在這裏找到不同的getter&setters(包括實時基準測試)的一個很好的概述:http://jsperf.com/object-defineproperty-vs-definegetter-vs-normal – 2012-04-05 20:45:38

9

這裏有一個乾淨的(ER)的替代(也可用於舊的腳本引擎):

function Test() { 
    var a=1; 
    return { A: { toString: function(){return a;} } }; 
} 

alert(Test().A); //=> 1 

你要知道,你不能用它來定義私有/靜態的複雜結構。你只能用這個模式'獲取'字符串或數字(所以不可變的變量)。也許模式可以使用json來增強。

[編輯]使用JSON,你還可以創建一個getter這樣的對象:

function Test() { 
    var a=1, 
    b = {foo:50, bar:100}; 

    return { 
      A: { toString: function(){return a;} } 
      foobar: { toString: function(){return JSON.stringify(b);} } 
     }; 
} 
var foobar = JSON.parse(Test().foobar); 
alert(foobar.foo); //=> 50 
+0

爲什麼你使用'A:{toString:function(){return a;}}'和'foobar:{toString:function(){return JSON.stringify(b);}}'而不是簡單的'A:return a;'和'foobar:return JSON.stringify(b)'? – Pacerier 2014-06-05 20:54:42

+0

@Prier他依賴於一些函數(比如'alert')的缺省行爲,它在任何不是字符串的參數上自動調用'.toString()'。 – Alnitak 2014-06-06 08:34:29

+0

@Alnitak,是的,爲什麼不簡單地返回'a',而不是返回一個通過toString返回'a'的對象?我的意思是有什麼區別...爲什麼不只是簡單地返回'a'? – Pacerier 2014-06-06 16:32:23

6

在Ecmascript5中, '乾淨'(與標準兼容)這樣做的方法是用defineProperty。

function Test() { 
    var a = 1; 
    Object.defineProperty(this, "A", {get : function() { 
      return a; 
     }, 
     enumerable : true}); 
} 

這假設你只是想看看如何定義一個getter。如果你想要做的是使測試的情況下不可變的(一個很好的事情,你可以),你應該使用該冷凍:

function Test() { 
    this.a = 1; 
    Object.freeze(this); 
} 
+1

這是不是(就像接受的答案)記憶?我對js很陌生,但在我看來,這些getter/setter屬於原型。 [this page](http://msdn.microsoft.com/en-us/library/dd548687(v = vs.94).aspx)建議說'Object.defineProperty(Test.prototype,「A」,{get :function(){...}})'應該可以在'Test'函數之後。這不是「更清潔」嗎? – Hans 2014-02-03 08:53:35

+0

是的,你是對的。我這樣做更像他在問題中的示例代碼,但通常我會希望在可能的情況下將原型放在原型上,我可能應該提出這一點。當然,另一個因素是,如果你這樣做,你必須把實際的價值放在'這個'上,這意味着你失去了信息隱藏的方面,這一直是一個恥辱。 – kybernetikos 2014-02-03 10:39:56

+0

@kybernetikos,那麼你是說Pointy的答案不符合標準? – Pacerier 2014-06-05 20:53:56