【问题标题】:Inheritance and Super in JavaScriptJavaScript 中的继承和超级
【发布时间】:2017-05-02 00:42:28
【问题描述】:

我正在学习 JavaScript 的第 3 天。我遇到了这段代码:

class B {
    constructor(name) {
        this.name = name;
    }

    printn() {
        return this.name;
    }
}

class A extends B {
    constructor(name, age) {
        super(name);
        this._age = age;
    }

    get age() {
        return this._age;
    }

    printName(){
        return super.printn();
    }
}

let c = new A("Testing", "37");
Console.log(c.printn());

谁能解释这段代码的作用。什么是构造函数和 super() 关键字?我相信他们是为了继承?我用谷歌找到了一些 tuts 但这似乎是最简单的例子,而且几乎没有解释。

我无法让这段代码工作。

【问题讨论】:

  • “我无法让这段代码工作。” – 为什么不呢?有什么问题?至于问题的“这是做什么的”部分......这是非常基本的OOP,之前肯定已经解释过很多次了。您是如何学习 Javascript 的?也许您需要更结构化的课程/教程/书籍。如果您处于一般编程的第 3 天(?),那么是的,OOP 可能有点早解决。如果您提出这些真正应该以结构化方式介绍给您的零碎问题,对您或这里的任何人都不会有成效。
  • 我推荐阅读 eloquentjavascript.netgithub.com/getify/You-Dont-Know-JS(技术性更强但非常好)来学习 JavaScript。

标签: javascript class inheritance ecmascript-6 super


【解决方案1】:

什么是构造函数和 super() 关键字。我相信是为了继承?

没错。上面设置类B,然后有类A子类。 constructor 是在创建类的新实例时调用的函数,如代码中的 let c = new A("Testing", "37"); 行所示。与其他一些语言不同,在 JavaScript 中,一个类只能有一个构造函数。

super 在子类中用于引用超类。在构造函数中,您调用super,就好像它是一个函数一样,它调用超类的构造函数,让它有机会对new 创建的新对象进行初始化.例如,在Aconstructor 中,super() 调用Bconstructor

您还可以使用super 作为属性访问器表达式的源来访问超类上的属性(包括方法)。这就是AprintName 方法中发生的事情,它使用super.printName() 调用BprintName 方法。 (这会失败,因为B 没有printName 方法;B 的方法称为printn。)

如果我没有指出,尽管这看起来很像 Java 或 C# 中的基于类的 OOP,我将是失职,但事实并非如此。它是一种语法糖(一种很好的糖),用于使用构造函数设置 JavaScript 的常规 原型 继承。它极大地简化了使用构造函数设置原型继承层次结构。如果我没有指出没有必要使用构造函数进行原型继承,我也会失职,您可以通过Object.create 不使用构造函数进行原型继承。

还有很多值得探索的地方。 MDN 可能是一个很好的起点。

我无法让这段代码工作。

Console.log 中的C 不应该大写,所以改变

Console.log(c.printn());

console.log(c.printn());

除此之外,如果您使用支持 class 的 JavaScript 引擎(例如 Google Chrome 或 Mozilla Firefox 中的引擎),则该代码可以正常工作,尽管再次注意 A 似乎期望 B有一个printName 方法,但它没有,最后的代码调用printn 只有B 有(这很好,它只是意味着A 的代码并没有真正参与)。

class B {
    constructor(name) {
        this.name = name;
    }

    printn() {
        return this.name;
    }
}

class A extends B {
    constructor(name, age) {
        super(name);
        this._age = age;
    }

    get age() {
        return this._age;
    }

    printName(){
        return super.printName();
    }
}

let c = new A("Testing", "37");
console.log(c.printn());

【讨论】:

  • 你的话刚刚流入我的脑海。惊人的。让我处理这些信息,如果有的话我会问更多问题。非常感谢先生。
  • 我相信 ES6 之前的版本没有类,所以他们使用原型。什么是原型继承,我将如何在其中编写相同的代码?你能解释一下,类是如何解决原型的问题的吗?
  • @BenAston:方法(在类和对象上)有一个有点令人惊讶的特性:它们有一个指向创建它们的对象(它们的 [[HomeObject]])的内置链接,并使用用于处理super——即使您已将该方法复制到一个完全不同的对象。你可以在不使用 class 的情况下完成 class 在 ES2015 中所做的所有事情,但这部分不是 ES5 所拥有的,所以那里有一个最微小的东西,它不是 ES5 机制上的纯语法糖(尽管它在ES2015 机制)。
  • @BenAston:为了清楚起见:这个对象有一个名为 foo 的方法分配给一个名为 foo 的属性:const obj = { foo() { } };。但是,这个对象只有一个名为foo函数分配给一个名为foo的属性:const obj = { foo: function() { } };。在后一种情况下,没有 [[HomeObject]] 设置,因此foo 将无法使用super(而在第一种情况下,它可以;它可以使用super.toString() 来执行@987654369 @,例如)。
  • @BenAston:此外,FWIW,通过类语法定义的方法不能用new 调用。并不是说任何人应该这样做,但它仍然是偏离了良好的旧 X.prototype.foo = function() {} 的行为。
【解决方案2】:

欢迎使用 JavaScript。祝你好运。我会将您的问题从您的具体问题改写为更一般的问题,即如何最好地学习 JavaScript。

首先,确保从编辑器或 IDE 开始组织环境。无论您选择哪一个,它都应该可以帮助您格式化、缩进、突出显示、检查,甚至可能运行您的代码。花时间学习如何根据自己的喜好进行配置。安装有用的插件。您将在 IDE 中花费数小时。像装修房子一样小心翼翼地布置它。

接下来,请确保您了解在哪里可以找到信息。 SO 上的一些人似乎认为它是一种人工文档服务。 MDN 几乎总是最好的资源。他们还提供教程,这是一个很好的起点。

接下来,熟悉 Chrome 开发工具。从头到尾阅读文档。了解如何使用控制台、源面板、断点和变量监视。归根结底,您必须调试自己的程序,尽管 SO 上的一些人似乎认为他们可以依靠社区来做到这一点。

现在谈谈语言本身。在进入课程之前,如果您还没有,我会确保您对基础知识非常熟悉:包括对象和数组的数据类型,以及条件和循环等基本控制结构。您应该准确了解对象是什么、属性是什么、如何以文字形式编写对象、如何设置和检索属性以及数组的等价概念。不断写小程序尝试一下;您可以在 devtools 控制台中运行它们。

确保您对函数有扎实的了解。 它们是 JS 逻辑的基本构建块。它们是参数化的逻辑束,接受定义明确的输入(参数)并产生明确定义的输出(返回值)。了解如何定义函数以及如何调用它们。当您处理一个问题时,考虑如何将其分解为可以实现为函数的子问题几乎总是一个很好的起点。

一旦您熟悉了数组和函数,请确保您牢牢掌握了以函数为参数的数组方法(函数)。这是正确的;在 JavaScript 中,函数是可以作为参数传递给其他函数的值。这是您对函数式编程的第一次温和介绍。学习 forEach 和相关的数组方法,您可以在其中传递一个函数来告诉它如何处理每个元素。

如果您从事前端工作,则需要非常熟悉 DOM。回到 devtools 并确保您了解如何使用 Elements 面板检查 DOM。了解用于创建元素、设置属性、将元素插入 DOM 以及在 DOM 中查找元素的基本 DOM API,例如 getElementById。同样,随着您的前进,不断编写小示例程序以确认您走在正确的轨道上并加强您的知识。在掌握 DOM 的同时,您需要开始学习 CSS,这是我们管理属性的方式,这些属性控制着 DOM 元素的样式(布局和格式化),以及 CSS 类,它们是可以应用的这些属性的捆绑包通过简单地将一个类分配给一个元素。花点时间掌握级联,这是 CSS 引擎决定将哪个规则应用于哪个元素的过程。再次回到 devtools 并确保您了解如何使用样式检查器检查 DOM 中的 CSS 属性。

您会注意到我们甚至还没有提到 JS 类,这就是您的问题所在。我有点惊讶你会在学习过程中这么早地钻研这个话题。类是特定程序设计风格的基础,通常称为面向对象编程或经典 OOP,其中涉及设计作为数据和相关功能捆绑的对象。有些人认为所有编程都是或应该是 OOP。还有其他人在完全不使用任何 OOP 原则的情况下成功编写了大型系统。

OOP 的问题在于,现实世界并没有将自己整齐地划分为动物、狗、车辆、汽车以及 As 和 B。在你定义了 Animals 和 Dogs 之后,你就会意识到你需要 Mammals 介于两者之间,在你知道之前,你最终会得到一个难以理解、维护和扩展的扭曲的类层次结构,并且你花了一半的时间来重新-安排。对于您试图解决的 IRL 问题,很可能不需要这些机器。一旦你有了 OOP 锤子,一切都开始看起来像钉子。不久之后,您将用新的 OOP 锤子敲打松软的意大利面和果冻块,或者只是在空中挥舞它。

【讨论】:

  • Nitpick - 我会将使用类描述为“经典 OOP”,而不仅仅是“OOP”。我相信没有类的 JavaScript 可以被描述为 OOP(尽管我不确定它是否符合 Kay 的定义,包括消息传递)。我完全同意你关于混合功能和数据的观点,这就是为什么我个人认为类对好的代码有害。简而言之,有害的不是 OOP,而是(恕我直言)古典风格。
  • 谢谢@torazaburo。我会听从建议的。
猜你喜欢
  • 2021-01-29
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多