[英]ES6: How to have a getter/setter for an object AND its properties
我旨在使用JS getter和setters創建以下API案例:
// the user should be able to write this to update thing
thing = {
x: 1,
y: 2
}
// OR they should be able to write this
thing.x = 1
thing.y = 2
現在我正在使用這樣的代碼:
get thing() {
return {
x: this._thing.x,
y: this._thing.y
};
}
set thing(value) {
this._thing.x = value.x,
this._thing.y = value.y
}
這支持第一種情況,但不支持第二種情況。
可以用任何合理的簡單方法來完成嗎?
編輯:我將鍵入一個示例,但為此的用例可能是thing.x
和thing.y
應該始終使用Math.round()
舍入為整數。
如果必須使用getter和setter,則相對簡單的解決方案是將x
和y
也定義為getter和setter。
get thing() {
var self = this;
return {
get x() {
return self._thing.x;
}
set x(value) {
self._thing.x = value;
}
// same for y
};
}
但是您必須意識到,每次訪問thing
進行讀取時 ,都會創建一個新對象。 盡管您可以通過緩存該對象並重用它來避免這種情況。
實際上,我可能_thing
。 我只存儲_x
和_y
並按需生成一個對象:
class Foo {
get thing() {
if (this._thing) {
return this._thing;
}
var self = this;
return this._thing = {
get x() {
return self._x;
}
set x(value) {
self._x = value;
}
};
}
set thing(value) {
this._x = value.x;
this._y = value.y;
}
}
...一個用例可能是
thing.x
和thing.y
應該始終使用Math.round()
舍入為整數。
考慮使用代理
class Parent { constructor() { this.thing = {x: 15.6, y: 2.1}; } set thing(value) { this._thing = new Proxy(value, { get: function(target, property, receiver) { // Catch all get access to properties on the object if (['x', 'y'].includes(property)) { // for x and y, return the real value, rounded return Math.round(target[property]); } } }); } get thing() { return this._thing; } } var parent = new Parent(); console.log(parent.thing.x); // 16 parent.thing.x = 13.2; console.log(parent.thing.x); // 13 parent.thing = {x: 10.1, y: 5.4}; console.log(parent.thing.y); // 5 // This works for the Jacque Goupil's conundrum var anotherRef = parent.thing; anotherRef.x = 5.8; console.log(parent.thing.x); // 6 // In fact, if you wanted to dance with the devil... var plainObj = {x: 10.1, y: 5.4}; parent.thing = plainObj; plainObj.x = 7.2; console.log(parent.thing.x); // 7 parent.thing.x = 22.2; console.log(plainObj.x); // 22.2
代理允許您捕獲屬性的獲取或設置操作。
警告: IE目前暫時不支持代理。 如果我有一個用於Google Proxy polyfill的CDN,我會將其添加到摘要中,但我沒有。 另外,如果您使用Babel ,則還有babel-plugin-proxy
我認為您不應該使用這種模式,並且我認為您將無法使其正常工作。 考慮以下情況:
// calls the position setter on foo
foo.position = {x: 10, y: 20};
// calls the position getter on foo, obtaining a simple {x:10,y:20} object
var pos = foo.position;
// calls the position getter on foo and then the x getter on position
var xx = foo.position.x;
到目前為止,一切都有意義。 然后我們進入這種情況:
// calls the position getter on foo and then the x setter on position
foo.position.x = 7;
由於我們返回了一個帶有位置獲取器的簡單地圖,所以position.x只是分配給返回的副本,而不會修改foo的實際位置。 解決此問題的一種方法是讓位置獲取器返回一個更智能的對象,該對象具有對foo實例和適當的獲取器/設置器的引用。 這將允許執行以下操作:
foo.position = bar.position;
bar.x += 10;
所述bar.position
吸氣劑都將返回一個僅作為一個視圖中的對象bar
“SX / y屬性。 然后, foo.position
設置程序會將bar
的sx / y屬性復制到其專用存儲中。 說得通。 bar.x += 10
廣告僅針對bar
的位置。
但是,以下情況將非常令人困惑:
var temp = foo.position;
foo.position = bar.position;
bar.position = temp;
這產生了一種幻覺,認為temp是foo.position
的備份副本,但事實並非如此。 這是一個觀點。 一旦foo的位置發生變化,我們就會永遠丟失數據。 沒有簡單的方法可以復制該職位。
您可以嘗試使position
對象實際存儲數據的副本以及原始數據的引用,以便既可以設置又可以獲取...這是一個無休止的問題。
但是在這一點上,您的糖語法使所有內容的維護變得更加困難,效率也大大降低。
因此,實際上我沒有做所有這些事情,而是使x和y getter / setters位於foo / bar對象本身上。 我還要使foo / bar對象內的任何代碼都將位置視為不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.