Javascript:为什么在子类中声明属性会将超类中的同一属性覆盖为null

Javascript:为什么在子类中声明属性会将超类中的同一属性覆盖为null,javascript,class,inheritance,Javascript,Class,Inheritance,我的问题与理解类如何为属性赋值以及对象如何在Javascript中实例化有关。我想更多地了解这个过程是如何工作的 如果我创建两个类,其中第二个继承第一个 class A { name constructor(name){ this.name = name } } class B extends A { name status constructor(name, status){ super(name)

我的问题与理解类如何为属性赋值以及对象如何在Javascript中实例化有关。我想更多地了解这个过程是如何工作的

如果我创建两个类,其中第二个继承第一个

class A {
    name

    constructor(name){
        this.name = name
    }
}

class B extends A {
    name
    status

    constructor(name, status){
        super(name)
        this.status = status
    }
}
然后创建一个类B的实例,当我将它打印到控制台时

x = new B('myClass', true)
console.log(x)
它显示名称变量未定义

B { name: undefined, status: true }

我很确定B中的name属性是在A中过度写入name属性,但为什么A构造函数不将新的name变量指定为传递给它的值呢?

这个例子是借用的,以表明这种行为不应该发生

类动物{
建造师(姓名){
this.name=名称;
}
讲{
log(`${this.name}发出噪音。`);
}
}
狗类动物{
建造师(姓名){
super(name);//调用super类构造函数并传入name参数
}
讲{
log(`${this.name}barks.`);
}
}
设d=新狗('Mitzie');

d、 讲()Mitzie barks.
目前这是正确的行为(2020年10月)

当你设定

class A {
    name
}
这声明了一个类字段。它还不是一个标准,它是。它可能会改变,但不会有太大的改变。阶段3是候选阶段,可能包括精加工

无论如何,根据提案的当前规范,您看到的是正确的。任何不带初始值设定项的类字段都设置为
未定义
。这是因为在
B
中有另一个名为
name
的类字段,而没有初始化器。父构造函数中发生的赋值将被覆盖

:

没有初始值设定项的字段设置为
undefined
无论是否存在初始值设定项,公共和私有字段声明都会在实例中创建字段。如果没有初始值设定项,则该字段设置为
undefined
。这与某些transpiler实现有所不同,后者只会完全忽略没有初始值设定项的字段声明

例如,在下面的示例中,
newd
将导致对象的
y
属性为
undefined
,而不是
1

C类{
y=1;
} 
D类扩展了C类{
Y
}
将没有初始值设定项的字段设置为
undefined
,而不是删除它们的语义是,字段声明提供了一个可靠的基础,以确保创建的对象上存在属性。这有助于程序员将对象保持在相同的一般状态,这可以使其易于推理,有时在实现中更易于优化


是的,我本不想两次宣布我的名字,但我有一个bug。你说BabelJS/es2015没有问题?这是否意味着我没有使用它们?我正在使用许多es6功能,如
=>
导入
。我很确定我也在用巴贝尔。我正在运行react应用程序并使用webpack。@Sam我无法察觉或回答环境问题,但选中特定复选框后,您的代码运行良好。所以,是的,巴贝尔可能没有加载,但从y端到判断,这是完全不确定的。在任何情况下,您都可以跳过
name
的第二个声明。这也是MDN示例的原因。重写给定的默认值时,在子类中重新声明变量是有意义的。例如,父类中的
name='John'
可以是子类中的
name='Peter'
。我在
B
的构造函数中调用
A
的构造函数。构造函数完成执行后,
name
的此字段是否已创建并初始化为
undefined
?因为否则我会期望
name
被初始化为
undefined
,但是
A
的构造函数会运行并覆盖它value@Sam是的,很明显,这个决定是为了确保没有初始值设定项的类字段总是
未定义。因此,在
B
中调用
super()`in
B
将初始化
this.name
in
A
,但一旦
B
,属性将被擦除回
未定义的
。似乎在没有初始值设定项的情况下声明类字段的行为就好像在调用
super()
之后有一个
name=undefined
。我不确定我是否同意这个决定,但在隔离可能影响对象的更改方面有一些逻辑。如果
A
没有
名称
,但后来更改为对其进行初始化,则可能会更改
B
的行为。