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);
我正在寻找一种优雅的方式来为 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);