ES5/6 类 中多个相同 getter/setter 函数的良好解决方案?

Good solution for multiple identical getter/setter functions in ES5/6 classes?

我正在寻找一种优雅的方式来为 ES6 classes 中的多个属性声明相同 getter/setters。

而不是有一系列的:

  set prop_1(value){
      this.prop_1 = value;
      console.log(`set prop_1 = ${value} and calling updateroom`);
      db.updateRoom(this, 'prop_1');
  }

...

  set prop_n(value){
      this.prop_n = value;
      console.log(`set prop1 = ${value} and calling updateroom`);
      db.updateRoom(this, 'prop_n');
  }

我想在与其他 getters 和设置器相邻的 class 定义中做一些更易于维护的事情:

['prop_1', 'prop_2' ... 'prop_n'].forEach(prop => {
      set [prop](value) {
        this[prop] = value;
        console.log(`set ${prop} = ${value} and calling updateroom`);
        db.updateRoom(this, prop);
      }
});

但是当然不能在 class 定义中这样做,因为文字不是语法上允许的内容之一。

甚至无法在稍后声明后将 setter 添加到 class 定义中,例如:

class Room {
// stuff
}

['initialised', 'type', 'owner'].forEach(prop => {
    Object.defineProperty(Room, prop, {
      set: function(value) {
        this[prop] = value;
        console.log(`set ${prop} = ${value} and calling updateroom`)
        db.updateRoom(this, prop);
      }
})

因为此时没有实例。

所以最终走上了装饰构造函数的神秘之路,这意味着任何想弄清楚我后来到底想实现什么的人都会头疼半小时,而且会更加复杂。

我是不是遗漏了什么,有没有人想出一种优雅的方式来有效地编码而不重复 getter-setters?

I'd like to do something a little more maintainable like this in the class definition adjacent to the other getters and setters:

['prop_1', 'prop_2' ... 'prop_n'].forEach(prop => {
      set [prop](value) {
        this[prop] = value;
        console.log(`set ${prop} = ${value} and calling updateroom`);
        db.updateRoom(this, prop);
      }
});

Can't even add the setters to the class definition after declaration later via e.g.:...as there is no instance at that point.

是的,但是您可以使用Object.defineProperty来做到这一点,在将成为这些实例原型的对象上设置属性(Room.prototype ). class 声明后:

class Room {
    // ...
}

...您可以将这些设置器添加到 Room.prototype:

['prop_1', 'prop_2'/* ... 'prop_n'*/].forEach(prop => {
    Object.defineProperty(Room.prototype, prop, {
        set: function(value) {
            // ...save the value somewhere (*NOT* `this[prop] = value;`,
            // which will call the setter again, resulting in a stack
            // overflow error...
        }
    });
});

请记住,class 表示法主要是原型继承的语法糖(但是,您知道,good 这种糖)。您仍然有一个 Room.prototype 对象,在 class 声明之外向其添加内容是完全有效的。

实时示例 (在这个示例中,我只是将值存储在单独的 values 属性 对象中):

class Room {
    constructor() {
       this.values = {};
    }
}
['prop_1', 'prop_2', 'prop_n'].forEach(prop => {
    Object.defineProperty(Room.prototype, prop, {
        set: function(value) {
            console.log(`set ${prop} = ${value}...`);
            this.values[prop] = value;
        },
        get: function() {
            return this.values[prop];
        }
    });
});

const r = new Room();
r.prop_1 = 42;
console.log("r.prop_1 = ", r.prop_1);
r.prop_2 = "Answer";
console.log("r.prop_2 = ", r.prop_2);