admin管理员组文章数量:1415645
My question has to do with understanding how classes assign values to properties and how objects are instantiated in Javascript. I would like to understand more how this process works.
If I create two classes where the second inherits from the first
class A {
name
constructor(name){
this.name = name
}
}
class B extends A {
name
status
constructor(name, status){
super(name)
this.status = status
}
}
And then create an instance of class B, when I print it to the console
x = new B('myClass', true)
console.log(x)
It prints that the name variable is undefined
B { name: undefined, status: true }
I'm pretty sure that the name property in B is over-writing the name property in A, but why doesn't the A constructor assign the new name variable to be the value passed into it?
My question has to do with understanding how classes assign values to properties and how objects are instantiated in Javascript. I would like to understand more how this process works.
If I create two classes where the second inherits from the first
class A {
name
constructor(name){
this.name = name
}
}
class B extends A {
name
status
constructor(name, status){
super(name)
this.status = status
}
}
And then create an instance of class B, when I print it to the console
x = new B('myClass', true)
console.log(x)
It prints that the name variable is undefined
B { name: undefined, status: true }
I'm pretty sure that the name property in B is over-writing the name property in A, but why doesn't the A constructor assign the new name variable to be the value passed into it?
Share Improve this question asked Oct 14, 2020 at 16:42 SamSam 2,41917 gold badges99 silver badges211 bronze badges2 Answers
Reset to default 3This is correct behaviour for the moment (October 2020).
When you set
class A {
name
}
This declares a class field. It's not a standard yet, it's a proposal in stage 4. It's likely to change but not by much. Stage 3 is the candidate stage and might include finishing refinements.
At any rate, what you are seeing is correct according to the current spec of the proposal. Any class fields without initialisers are set to undefined
. This happens because you have another class field called name
in B
without an initialiser. The assignment that happens in the parent constructor will be overwritten.
Here is the relevant part of the proposal that discusses this behaviour:
Fields without initializers are set to
undefined
Both public and private field declarations create a field in the instance, whether or not there's an initializer present. If there's no initializer, the field is set to
undefined
. This differs a bit from certain transpiler implementations, which would just entirely ignore a field declaration which has no initializer.For example, in the following example,
new D
would result in an object whosey
property isundefined
, not1
.class C { y = 1; } class D extends C { y; }
The semantics of setting fields without initializers to
undefined
as opposed to erasing them is that field declarations give a reliable basis to ensure that properties are present on objects that are created. This helps programmers keep objects in the same general state, which can make it easy to reason about and, sometimes, more optimizable in implementations.
This example is borrowed from MDN in order to indicate that this behavior should not happen.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
If you check the Use BabelJS / ES2015
checkbox in the snippet configuration in SO no problem occurs for your code.
class A {
name;
constructor(name){
this.name = name;
}
}
class B extends A {
name;
status;
constructor(name, status){
super(name);
this.status = status;
}
}
let a = new B('myClass',true);
console.log(a);
But if you uncheck it...
class A {
name;
constructor(name){
this.name = name;
}
}
class B extends A {
name;
status;
constructor(name, status){
super(name);
this.status = status;
}
}
let a = new B('myClass',true);
console.log(a);
...the same code provides the error you noticed.
So what is actually the problem and how to solve this? There is no need to set name
again in the child class. If you don't, here is the result:
class A {
name;
constructor(name){
this.name = name;
}
}
class B extends A {
status;
constructor(name, status){
super(name);
this.status = status;
}
}
let a = new B('myClass',true);
console.log(a);
本文标签:
版权声明:本文标题:Javascript: Why does declaring a property in a subclass overwrite the same property in a super class as null - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745173392a2646111.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论