Heim > Web-Frontend > js-Tutorial > Hauptteil

Eine ausführliche Erklärung des JavaScript-Vererbungssystems

黄舟
Freigeben: 2017-10-23 09:39:06
Original
1223 Leute haben es durchsucht

1. Prototypattribute und Prototypobjekte von Konstruktoren

Wenn ich zum ersten Mal mit js in Kontakt komme, folge ich normalerweise dem gleichen Beispiel und verwende die Funktion neu Ich weiß es nicht, weil ich nur gehört habe, dass Funktionen in js Objekte sind. Es stellt sich heraus, dass js in Sprachen wie Java nicht das Klassenvererbungssystem verwendet, sondern Prototypobjekte (Prototypen) zur Implementierung des Vererbungssystems verwendet. Insbesondere werden „Konstruktoren“ zur Implementierung von Klassenfunktionen verwendet.

Erklären Sie zunächst die beiden wichtigen Konzepte der prototypischen Vererbung: Prototypattribute und Prototypobjekte (Instanzen).

Was das js-Objektsystem betrifft, verfügt jede erstellte Funktion (Konstruktor) über ein Prototyp-Prototypattribut. Gleichzeitig enthält jede über den Konstruktor erstellte Objektinstanz auch ein _proto_-Attribut, einen Prototyp und einen _proto_. Das Attribut ist ein Zeiger auf das Prototypobjekt. Der einzige Unterschied zwischen einer gewöhnlichen Funktion und einem Konstruktor besteht darin, ob ihr Prototyp-Attribut „Prototyp“ einen sinnvollen Wert hat.

Der Prototyp, auf den das Prototypattribut „Prototyp“ verweist, ist eine Objektinstanz. Insbesondere, wie in der folgenden Abbildung gezeigt, müssen alle vom Konstruktor erstellten Instanzen nach B kopiert werden, wenn der Konstruktor Animal() über ein Prototypobjekt B verfügt. Das heißt: Das _proto_-Attribut der Instanz a1 von Animal() zeigt auch auf das Prototypobjekt B. Daher kann Instanz a1 alle Eigenschaften, Methoden und anderen Eigenschaften von B erben.

Abbildung 1 Implementierung der js-Objektinstanziierung

2. Leeres Objekt

In JavaScript, „leeres Objekt“, ist die Grundlage des gesamten Prototypenvererbungssystems und die Grundlage aller Objekte. Bevor wir „leere Objekte“ einführen, müssen wir zunächst „leere Objekte (null)“ einführen.

Leeres Objekt null

Null ist kein „leeres Objekt“. Als reserviertes Wort in JavaScript lautet seine Bedeutung:

(1) Es gehört zum Objekttyp

 (2) Das Objekt ist ein Nullwert

Als Objekttyp können Sie for...in zum Aufzählen verwenden, aber als Nullwert verfügt null über keine Methoden und Attribute (einschließlich Konstruktor, _proto_ und andere Attribute), sodass nichts aufgelistet werden kann. Wie im folgenden Beispiel gezeigt:


var num=0;
  for(var propertyName in null)
  {
  num++;
  }
Nach dem Login kopieren

Alert(num);//Der angezeigte Wert ist 0

Der wichtigste Punkt ist, dass null hat keinen Prototyp, es wird nicht vom Object()-Konstruktor (oder seiner Unterklasse) instanziiert und die Instanzoperation darauf gibt false zurück.

 2. „Leeres Objekt“

  „Leeres Objekt“ bezieht sich auf eine Standardobjektinstanz, die über Object() erstellt wurde. Zum Beispiel:


obj=new Object();或 obj={};
Nach dem Login kopieren

Ein „leeres Objekt“ hat alle Eigenschaften eines „Objekts“, sodass es auf vordefinierte Eigenschaften und Methoden wie toString() und zugreifen kann Wertvon.

 3. Die Beziehung zwischen „leerem Objekt“ und null

Wie im Pfad gezeigt, der durch die rote Linie in Abbildung 2 unten gezeigt wird, wenn das -proto-Attribut des Objektprototypobjekts ist erhalten durch „Object.prototype._proto_“ Wenn Sie „null“ erhalten, da das Nullobjekt keine Attribute hat, also „Objekt {}“

Das Prototypobjekt ist das Ende der Prototypenkette.

Abbildung 2 js-Klassenvererbungssystem

3. Implementierung der Javascript-Vererbung und Prototypkettenwartung

(1) Implementierung der Vererbung

Im ersten Abschnitt wurde gesagt, dass die Klassenvererbung in JavaScript durch Ändern des Prototypattributs des Konstruktors implementiert wird. Wie im folgenden Code gezeigt:


function Animal() {
this.name = 'Animal';
};
function Dog() {
};
  Dog.prototype = new Animal();
var d = new Dog();
console.log(d.name);//'Animal'
Nach dem Login kopieren

Die Typvererbung wird erreicht, indem eine Instanz des Tiertyps erstellt und diese dem Prototypattribut des Konstruktors Dog() zugewiesen wird. Das heißt, Animal ist die übergeordnete Klasse von Dog. Auf diese Weise kann die Instanz d vom Typ Hund auch auf das Namensattribut vom Typ Tier zugreifen.

(2) Prototypenkette

Es gibt zwei Prototypenketten im JS-Objektvererbungssystem: „interne Prototypenkette“ und „Konstruktor-Prototypkette“. Wie in Abbildung 3 dargestellt, zeigt der schwarze Pfeil an, dass der Pfad die „Konstruktor-Prototypkette“ ist, die über das Prototypattribut des Konstruktors verwaltet wird. Der rote Pfeil zeigt an, dass der Pfad die „interne Prototypenkette“ ist, die über das _proto_-Attribut der Objektinstanz verwaltet wird.

Abbildung 3 Prototypenkette

(3) Wartung der Prototypenkette

Abbildung 3 zeigt, dass der Konstrukteur anhand des angezeigten Prototyps einen Prototyp erstellt Kette und Objektinstanzen bilden auch eine Prototypenkette über das Attribut _proto_. Da _ proto _ eine nicht zugängliche interne Eigenschaft ist (der Wert der Eigenschaft object _ proto _ kann in Chrome angezeigt, aber nicht geändert werden), kann ab der Instanz dog1 der Unterklasse (Dog) nicht auf die gesamte Prototypenkette zugegriffen werden. Daher müssen wir einen Verbindungspunkt zwischen der „internen Prototypenkette“ und der „Konstruktor-Prototypkette“ in Abbildung 3 finden, damit, wenn die Instanz nicht auf obj._proto_ zugreifen kann, über den Konstruktor (die beiden Prototypen) auf die interne Prototypenkette zugegriffen wird sind in Reihe verkettet).

Um ausgehend von einer Instanz einer Unterklasse auf die gesamte Prototypenkette zuzugreifen, müssen Sie das Konstruktorattribut der Instanz verwenden, um die Prototypenkette zu verwalten.

其实,JavaScript已经为构造器维护了原型属性,根据如下测试代码,当我们自定义一个构造器时,其原型对象是一个Object()类型的实例,但是其原型对象的constructor属性默认总是指向构造器自身,而非指向其父类Object。如图4中构造器实例中蓝色框中的constructor属性,该constructor属性继承自原型对象,因此可以得出一个自定义的构造器产生的实例,其constructor属性默认总是指向该构造器。


function Animal() {
};
var a = new Animal();
console.log(Animal.prototype);//Object(){}
console.log(Animal.prototype.constructor === Animal);//true//true
Nach dem Login kopieren

  

图4

  因此,在_proto_属性不可访问时,可通过a1.constructor.prototype获取实例a1的原型对象。然而,当我们自定义一个构造函数Dog(),并且手动指定其prototype属性值为Animal,即指定Dog的父类为Animal。此时访问d1.constructor值为Animal,而不是Dog;由图5可以看出,Dog的原型对象和dog分别由Animal()和Dog()两个不同的构造器产生,然而他们的constructor属性指向了相同的构造器(Animal),这样就与使用constructor属性串联两种原型链的设想冲突了。

图5

  是构造器出问题还是原型出了问题?图5可以看出,原型继承要求的“复制行为”已经正确实现,能够从子类实例中访问原型对象属性,问题是在给子类构造器Dog()赋予一个原型对象时应该“修正”该原型对象的构造属性值(constructor)。ECMAScript 3标准提供的方法是:保持原型的构造器属性,在子类构造器中初始化其实例对象的构造属性。代码如下: 


function Dog () {
  //初始化constructor属性
   this.constructor=Dog; //或 this.constructor=arguments.callee;
  };
  Dog.prototype = new Animal();//赋予原型对象,实现继承
Nach dem Login kopieren

图6

对constructor属性“修正”后效果如图6所示,在子类构造器Dog中初始化其实例对象的constructor属性后,Dog的实例对象的constructor都指向Dog,而Dog的原型对象的constructor仍然指向父类型构造器Animal。这样就可以实现利用constructor属性串联起原型链,可以从子类实例开始回溯整个原型链。

总结

Das obige ist der detaillierte Inhalt vonEine ausführliche Erklärung des JavaScript-Vererbungssystems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage