If I have a super class that is supposed to be able to set some initial properties on a new instance, why do the members of the child class seem to override the constructor of the super class?
class Base {
constructor(fields) {
Object.assign(this, fields)
}
}
class Foo extends Base {
time = 0;
// calling super seems to make no difference
// constructor(...args) {
// super(...args)
// }
}
const foo = new Foo({ time: 22 })
console.log(foo.time) // is 0, should be 22?
If I remove time = 0;
from the child class it works as expected but my linter breaks.
How can I retain the member initializer, i.e., time = 0;
in the child class but have the super class be able to set properties in its constructor?
CodePudding user response:
Instances may only be accessed after a super
call is complete. Without the class field, look at the error:
class Base {
constructor(fields) {
Object.assign(this, fields)
}
}
class Foo extends Base {
constructor(...args) {
this.time = 0;
super(...args)
}
}
const foo = new Foo({ time: 22 })
Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Class fields follow this same logic by assigning to the instance only after the super call is complete. So
class Foo extends Base {
time = 0;
constructor(...args) {
super(...args)
is equivalent to
class Foo extends Base {
constructor(...args) {
super(...args)
this.time = 0;
In other words - the properties assigned inside the constructor (or class field) of a subclass is designed to override the properties assigned in a superclass constructor.
but have the super class be able to set properties in its constructor?
One approach would be to the default value for the time
property to 0, then pass and use that instead of a class field:
class Base {
constructor(fields) {
Object.assign(this, fields)
}
}
class Foo extends Base {
constructor({ time = 0, ...rest }) {
super({ time, ...rest })
}
}
const foo = new Foo({ time: 22 })
console.log(foo.time)