我有一个被许多其他类扩展的类。
我通过这些类的实例传递数据,它们似乎调用了主类的“ 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与父类中包含的单个变量和最终值相关,这意味着必须在不同的时间调用每个类才能起作用?确实有效。
有人可以解释一下吗?
同样,在首次加载应用程序时,类似乎互相调用以发送数据,从而“解析”了数据-这是怎么回事?也许我需要阅读一些计算机科学书籍,并了解有关如何调用类,它们的序列以及如何将数据分配给实例以及它如何工作的所有细节。
答案 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
都具有该隐式构造函数。因此C
用new 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) | +−−−−−−−−−−−−−−−−−−−−−+