了解Javascript / Typescript类并对其进行扩展

时间:2019-03-12 16:03:45

标签: javascript typescript

我有一个被许多其他类扩展的类。

我通过这些类的实例传递数据,它们似乎调用了主类的“ this”属性,并且每个人都可以做到这一点,这是否意味着它们具有该值的自己的“副本” ?

我真的很想了解这一切是如何工作的,数据如何通过这些类并专门用于每个类,Il显示代码:

父类(只是其中的相关部分):

export abstract class EngagementGraphNode {
  public endpoint: string;
  public id: string;
  public name: string;
  public x?: number;
  public y?: number;
  public parent?: EngagementGraphNode;
  public children: EngagementGraphNode[] = [];
}

然后我有一个可访问某些属性的类,例如this.children:

export class EngagementProduct extends EngagementGraphNode {
  public engagements: Engagement[] = [];
  public description: string;
  public timelineRows: TimelineRow[] = [];

  setProperties(json: IEngagementGraphNode, placeholder: string, color: string) {
}

  setChildren(filters: IFilterParams, rebuild: boolean): void {
    let list = [];
    this.engagements.forEach(engagement => {
      const item = this.find(engagement, filters, rebuild);
      if (this.matchFilters(engagement, filters) && item) { list.push(item) }
    });
      this.children = list;
}

然后还有其他几个也使用'this.children'的类

我认为每个this.children与父类中包含的单个变量和最终值相关,这意味着必须在不同的时间调用每个类才能起作用?确实有效。

有人可以解释一下吗?

同样,在首次加载应用程序时,类似乎互相调用以发送数据,从而“解析”了数据-这是怎么回事?也许我需要阅读一些计算机科学书籍,并了解有关如何调用类,它们的序列以及如何将数据分配给实例以及它如何工作的所有细节。

1 个答案:

答案 0 :(得分:3)

该属性属于objct,而不是类。该属性可用于所有类中的代码,因为表达式this.children与类无关,它与对象this所引用的对象以及是否具有名为{{1 }}。确实如此,因此属性访问器起作用。

让我们简化一下。假设您有:

children

class A { constructor(answer) { this.answer = answer; } aMethod() { console.log("aMethod: " + this.answer); } } class B extends A { bMethod() { console.log("bMethod: " + this.answer); } } class C extends B { cMethod() { console.log("cMethod: " + this.answer); } } const first = new C(42); first.aMethod(); // 42 first.bMethod(); // 42 first.cMethod(); // 42仅创建一个对象。它具有类new C(42),类A和类B的功能(例如方法),因为它继承自与那些类关联的原型。创建对象(C之后,您在内存中的内容(忽略一些细节)看起来像这样:

           +−−−−−−−−−−−−−−−+
first−−−−−>|  (C Object)   |
           +−−−−−−−−−−−−−−−+       +−−−−−−−−−−−−−−−−−−−−−+
           | [[Prototype]] >−−−−−−>|     C.prototype     |
           | answer: 42    |       +−−−−−−−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−+
           +−−−−−−−−−−−−−−−+       | [[Prototype]]       >−−>|     B.prototype     |
                                   | cMethod: (function) |   +−−−−−−−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−+
                                   +−−−−−−−−−−−−−−−−−−−−−+   | [[Prototype]]       >−−>|     A.prototype     |
                                                             | bMethod: (function) |   +−−−−−−−−−−−−−−−−−−−−−+
                                                             +−−−−−−−−−−−−−−−−−−−−−+   | [[Prototype]]       >−−>(Object.prototype)
                                                                                       | aMethod: (function) |
                                                                                       +−−−−−−−−−−−−−−−−−−−−−+

在其上调用方法时,通常情况下,first指的是在其上调用了该方法的对象,该对象上具有属性this,因为answer构造函数它在那里。定义该方法的位置无关紧要,A仍然引用相同的单个对象。

如何调用this构造函数以将A放在那里?如果您没有为子类编写构造函数,那么JavaScript引擎会为您创建一个类似以下内容的构造函数:

answer

constructor(...args) { super(...args); } B都具有该隐式构造函数。因此Cnew C(42)调用C的构造函数,后者用42调用B的构造函数,后者用42调用A的构造函数42,将其放在通过this.answer = answer;创建的对象上。

如果您要做为子类编写构造函数,则它必须调用super(并且必须在使用this之前调用它),所以一种方法还是另一种方法,A将被呼叫。

要查看该属性属于该对象,让我们创建两个对象而不是一个:

class A {
    constructor(answer) {
        this.answer = answer;
    }
    aMethod() {
        console.log("aMethod: " + this.answer);
    }
}
class B extends A {
    bMethod() {
        console.log("bMethod: " + this.answer);
    }
}
class C extends B {
    cMethod() {
        console.log("cMethod: " + this.answer);
    }
}
const first  = new C(42);
const second = new C(67);
first.aMethod();  // 42
second.aMethod(); // 67
first.bMethod();  // 42
second.bMethod(); // 67
first.cMethod();  // 42
second.cMethod(); // 67

现在,内存中的内容看起来像这样-唯一的变化是现在有了一个second对象。

           +−−−−−−−−−−−−−−−+
first−−−−−>|  (C Object)   |
           +−−−−−−−−−−−−−−−+
           | [[Prototype]] >−−−+
           | answer: 42    |   |
           +−−−−−−−−−−−−−−−+   |
                               |   +−−−−−−−−−−−−−−−−−−−−−+
                               +−−>|     C.prototype     |
           +−−−−−−−−−−−−−−−+   |   +−−−−−−−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−+
second−−−−>|  (C Object)   |   |   | [[Prototype]]       >−−>|     B.prototype     |
           +−−−−−−−−−−−−−−−+   |   | cMethod: (function) |   +−−−−−−−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−−+
           | [[Prototype]] > −−+   +−−−−−−−−−−−−−−−−−−−−−+   | [[Prototype]]       >−−>|     A.prototype     |
           | answer: 67    |                                 | bMethod: (function) |   +−−−−−−−−−−−−−−−−−−−−−+
           +−−−−−−−−−−−−−−−+                                 +−−−−−−−−−−−−−−−−−−−−−+   | [[Prototype]]       >−−>(Object.prototype)
                                                                                       | aMethod: (function) |
                                                                                       +−−−−−−−−−−−−−−−−−−−−−+