The issue in question relates to human readability and data organization. I would like to assign getters and setters as children of class field properties, however I can’t get this
to reference the class prototype data. I think this is the same problem solved by using self
in a class constructor, but applied to class fields instead. Is there a comparable solution for class fields that would keep these definitions out of the constructor?
This is the format I would like to achieve. The constructor is not invoked because external data is not required for these field definitions. This throws a recursion error.
class data_controller {
// class fields
id = 12;
a = 10;
b = 20;
// log data entries
log = {
entry: {
get a() {
return {
id: this.id,
value: this.a,
label: 'a',
};
},
get b() {
return {
id: this.id,
value: this.b,
label: 'b',
};
},
},
};
// update data
update = {
set a(value) {
this.a = value;
},
set b(value) {
this.b = value;
},
};
}
// class usage
const data = new data_controller();
console.log(data.log.entry.a);
console.log(data.log.entry.b);
data.update.a = 50;
data.update.b = 60;
console.log(data.log.entry.a);
console.log(data.log.entry.b);
This is the format using ‘self’ and the constructor. I would like to keep the constructor free of these definitions.
class data_controller {
// class fields
id = 12;
a = 10;
b = 20;
log = {};
update = {};
constructor() {
self = this;
// log data entries
this.log.entry = {
get a() {
return {
id: self.id,
value: self.a,
label: 'a',
};
},
get b() {
return {
id: self.id,
value: self.b,
label: 'b',
};
},
};
// update data
this.update = {
set a(value) {
self.a = value;
},
set b(value) {
self.b = value;
},
};
}
}
// class usage
const data = new data_controller();
console.log(data.log.entry.a);
console.log(data.log.entry.b);
data.update.a = 50;
data.update.b = 60;
console.log(data.log.entry.a);
console.log(data.log.entry.b);
This is a format which keeps the constructor free of definitions but does not implement the getter/setter class usage.
class data_controller {
// class fields
id = 12;
a = 10;
b = 20;
// log data entries
log = {
entry: {
a: () => {
return {
id: this.id,
value: this.a,
label: 'a',
};
},
b: () => {
return {
id: this.id,
value: this.b,
label: 'b',
};
},
},
};
// update data
update = {
a: (value) => {
this.a = value;
},
b: (value) => {
this.b = value;
},
};
}
// class usage
const data = new data_controller();
console.log(data.log.entry.a());
console.log(data.log.entry.b());
data.update.a(50);
data.update.b(60);
console.log(data.log.entry.a());
console.log(data.log.entry.b());
I believe I could also solve this issue by making the class field organization flat, but I would like to maintain multi-level structures.
2
Answers
You can add a reference to the containing object in the nested objects. It’s
parent
in the code below. Then you can usethis.parent
to go up a level.I would suggest to refactor this into multiple separate classes, but if you insist on nesting…
You can also place them in some other method and just call that from your constructor. Or you can even create the objects using methods: