我正在寻找一种优雅的方法来为ES6类中的多个属性声明相同的getter / setter。
而不是有一大堆:
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');
}
我想在与其他getter和setter相邻的类定义中做一些像这样可维护的东西:
['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);
}
});
但当然不能在类定义中做到这一点,因为文字不是句法允许的东西之一。
稍后通过例如:
声明后,甚至无法将setter添加到类定义中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);
}
})
因为那时没有实例。
所以最终走下了一条装饰构造函数的神秘路径,这意味着任何人都试图找出我之后想要实现的目标,最终导致半小时的头痛和更复杂的事情。
我错过了什么,有没有人想出一种优雅的编码方式,而不重复吸气装置?
答案 0 :(得分:2)
我想在与其他getter和setter相邻的类定义中做一些像这样可维护的东西:
['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); } });
和
在稍后通过例如:......声明后,甚至无法将setter添加到类定义中,因为此时没有实例。
是的,但可以使用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
符号主要是关于原型继承的语法糖(但是,你知道,好的种糖)。你仍然有一个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);