为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕婉清6462132 2023-05-11 09:51:44
我的问题与理解类如何为属性赋值以及如何在 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 变量分配为传递给它的值?
查看完整描述

2 回答

?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

目前(2020 年 10 月)这是正确的行为。

当你设置

class A {
    name
}

这声明了一个类字段。这还不是一个标准,它是第 4 阶段的提案。它可能会改变,但不会太大。第 3 阶段是候选阶段,可能包括完成改进。

无论如何,根据提案的当前规范,您所看到的是正确的。任何没有初始化器的类字段都设置为undefined. 发生这种情况是因为您在没有初始化程序的情况下调用了另一个类name字段B。父构造函数中发生的赋值将被覆盖。

以下是讨论此行为的提案的相关部分:

没有初始值设定项的字段设置为undefined

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

例如,在以下示例中,将生成属性为而非 的new D对象。yundefined1

class C {
  y = 1; 
} 
class D extends C {
  y; 
}

在没有初始化器的情况下设置字段而不是擦除它们的语义undefined是字段声明提供可靠的基础以确保属性存在于创建的对象上。这有助于程序员将对象保持在相同的一般状态,这可以使推理变得容易,有时在实现中更可优化。


查看完整回答
反对 回复 2023-05-11
?
缥缈止盈

TA贡献2041条经验 获得超4个赞

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);


查看完整回答
反对 回复 2023-05-11
  • 2 回答
  • 0 关注
  • 154 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信