簡體   English   中英

ES6:如何對對象及其屬性進行吸氣/設置

[英]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.xthing.y應該始終使用Math.round()舍入為整數。

如果必須使用getter和setter,則相對簡單的解決方案是將xy也定義為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.xthing.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM