Каков наилучший способ обобщить сеттеры и геттеры в этом классе:
class A {
constructor() {
this._foo = new Foo();
this._bar = new Bar();
}
get foo() {
return this._foo;
}
set foo(value) {
if (value instanceof Foo)
this._foo = value;
else
this._foo = Object.assign(new Foo(), value);
}
get bar() {
return this._bar;
}
set bar(value) {
if(value instanceof Bar)
this._bar = value;
else
this._bar = Object.assign(new Bar(), value);
}
}
редактировать
Да, вопрос может быть основан на мнении и может быть обойден с печатным языком. Но как разрешить это в es6 для существующих проектов без возможности миграции?
Мне нужны эти сеттеры для определения типа членов после десериализации документа json, сохраненного в базе данных:
{
"foo" :{"x":0,"y":0,"z":0},
"bar" : {"propA": "valueA", "propB": "valueB"}
}
Вы можете теоретически использовать миксин:
const Typed = (key, type, parent = class {}) => class Typed extends parent {
constructor(...props) {
super(...props);
this['_${key}'] = new type();
}
get [key]() { return this['_${key}']; }
set [key](value) {
this['_${key}'] = value instanceof type ? value : Object.assign(new type, value);
}
}
const A = Typed("foo", Foo, Typed("bar", Bar, class {
//...
});
Но вам, вероятно, не следует вообще использовать getter/setters, а скорее исправить код, который пытается установить свойство с недопустимыми значениями.
Если вы хотите абстрагировать создание сеттеров/геттеров, вы, конечно, можете написать функцию, которая сделает это:
function typedAccessor(obj, name, type, internal) {
Object.defineProperty(obj, name, {
get() {
return this[internal];
},
set(val) {
if (val instanceof type)
this[internal] = val;
else
this[internal] = Object.assign(new type, val);
}
});
}
class A {
constructor() {
this._foo = new Foo();
this._bar = new Bar();
}
}
typedAccessor(A.prototype, "foo", Foo, "_foo");
typedAccessor(A.prototype, "bar", Bar, "_bar");
Однако я бы порекомендовал избегать этого паттерна.
Мне нужны эти сеттеры, чтобы определить тип членов после десериализации документа json
Лучше использовать пользовательский статический метод, который знает, как работать с представлениями JSON, чем делать Object.assign
(и надеяться, что все имеет правильные установщики). Это дает вам намного лучший контроль над процессом сериализации/десериализации и делает ваш класс проще, с меньшим количеством стандартного кода.
class A {
constructor(foo, bar) {
this.foo = foo;
this.bar = bar;
}
static fromJSON(val) {
return new this(Foo.fromJSON(val.foo), Bar.fromJSON(val.bar);
}
}