2012-07-26 44 views
0

昨天我發佈了大約prototypal inheritance and constructors。我最終選擇的是保持代碼漂亮和整潔,獨自離開了樣機的可能小的性能影響成本的方法:公共getter和setter方法的JavaScript對象

function Card(value) { 
    // setValue is a public instance method 
    this.setValue = function (val) { 
     if (!range[val]) { 
      val = drawRandom(); 
     } 

     // value is a public instance variable 
     this.value = val; 

     return val; 
    }; 

    this.setValue(value); 
} 

我的這種方法的問題,然而,就是我要調用的setValue方法,每當我想設置卡實例的值來驗證。我想要做的是有一個自定義的setter方法。這是我到目前爲止:

function Card(val) { 
    // value is a private instance variable 
    var value; 

    // This is a private instance method 
    // It's also self-invoking, but that's beside the point 
    (function (x) { 
     if (!range[x]) { 
      x = drawRandom(); 
     } 

     value = x; 
    }(val)); 

    this.__defineGetter__("value", function() { 
     return value; 
    }); 

    // Some code duplication 
    this.__defineSetter__("value", function (x) { 
     if (!range[x]) { 
      return false; 
     } 

     value = x; 

     return x; 
    }); 
} 

這很好。調用var card = new Card()給了我一個隨機值的實例,並且調用card.value = null失敗,因爲它超出範圍。

我的問題,這一點,不是事實,這顯然是更長的時間等,是它好像我複製一些代碼。如果setter方法和構造函數一起被調用,那將會很好。這樣,我可以消除整個自行調用的私有實例方法。

+0

爲什麼不乾脆在定義setter方法後寫'this.value = val;'? (對不起,我花了這麼多的嘗試正確地評論這個評論:-) – Pointy 2012-07-26 19:49:35

+1

' Object.defineProperty'被更廣泛的支持 – 2012-07-26 19:51:16

回答

1

首先,您應始終將value設置爲obj.value = newValue,即使在內部也是如此,因爲它會調用您的驗證。當這意味着構造函數:

this.value = val; 

但是,如果你的setter和getter聲明它之前,將無法正常工作。因此,在之後移動它,這樣setter函數在設置時就會存在。


工作示例這裏:http://jsfiddle.net/8tCjm/4/

var drawRandom = function() { 
    return Math.floor(Math.random() * 3) + 1; 
}; 

var range = { 
    1: 'Ace', 
    2: 'Two', 
    3: 'Three' 
}; 

function Card(val) { 
    var value; 

    this.__defineGetter__('value', function() { 
     return value; 
    }); 

    this.__defineSetter__('value', function (x) { 
     if (range[x]) { 
      value = x; 
     } else { 
      value = drawRandom(); 
     } 

     return value; 
    }); 

    this.value = val; 
}; 

console.log(new Card(1).value); // 1 
console.log(new Card(2).value); // 2 
console.log(new Card(3).value); // 3 

console.log(new Card(987).value); // not 987 (1-3) 
​ 
+0

我不知道我理解你的建議。 'this.value'意味着價值將成爲公共財產,我不能通過setter函數來保護它。此外,如果給定的值不在範圍內,我只希望該值是隨機的。 – 2012-07-26 20:03:06

+1

如果您在創建setter函數後從構造函數內部調用this.value',則會調用並使用setter函數。 'this.value = 123'和'obj.value = 123'做同樣的事情,如果this === obj'。雖然重讀你的問題,你可能需要'this.value = value;'來代替。如果這超出範圍,二傳手會解決它。 – 2012-07-26 20:07:54

+0

我嘗試在我的setter中將'return value'更改爲'return this.value' in my getter和'value = x' to'this.value = x'並且Firefox死了:'too much recursion:this.value = x; ' – 2012-07-26 20:17:52

2

功能是在Javascript第一類對象,所以你完全可以只做這樣的事情,以消除重複:

function setter (x) { 
    if (!range[x]) { 
     return false; 
    } 
    return x; 
} 
(function (x) { 
    value = setter(x); 
    if (!value) { 
     value = drawRandom(); 
    } 

}(val)); 

this.__defineGetter__("value", function() { 
    return value; 
}); 

// Some code duplication 
this.__defineSetter__("value", setter); 
+0

這個工作很好,但是最終我和Alex的解決方案一起工作。 – 2012-07-26 20:48:17