猿问

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

我的问题与理解类如何为属性赋值以及如何在 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 变量分配为传递给它的值?


慕婉清6462132
浏览 155回答 2
2回答

慕桂英4014372

目前(2020 年 10 月)这是正确的行为。当你设置class A {     name }这声明了一个类字段。这还不是一个标准,它是第 4 阶段的提案。它可能会改变,但不会太大。第 3 阶段是候选阶段,可能包括完成改进。无论如何,根据提案的当前规范,您所看到的是正确的。任何没有初始化器的类字段都设置为undefined. 发生这种情况是因为您在没有初始化程序的情况下调用了另一个类name字段B。父构造函数中发生的赋值将被覆盖。以下是讨论此行为的提案的相关部分:没有初始值设定项的字段设置为undefined公共和私有字段声明都会在实例中创建一个字段,无论是否存在初始化程序。如果没有初始值设定项,则该字段设置为undefined. 这与某些转译器实现有些不同,后者会完全忽略没有初始化器的字段声明。例如,在以下示例中,将生成属性为而非 的new D对象。yundefined1class C {   y = 1;  }  class D extends C {   y;  }在没有初始化器的情况下设置字段而不是擦除它们的语义undefined是字段声明提供可靠的基础以确保属性存在于创建的对象上。这有助于程序员将对象保持在相同的一般状态,这可以使推理变得容易,有时在实现中更可优化。

缥缈止盈

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.如果您选中Use BabelJS / ES2015SO 中代码段配置中的复选框,则您的代码不会出现任何问题。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);但是如果取消勾选... 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);...相同的代码提供了您注意到的错误。那么究竟是什么问题以及如何解决呢?无需name在子类中再次设置。如果不这样做,结果如下: 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);
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答