Heim > Web-Frontend > js-Tutorial > Hauptteil

JavaScript objektorientiert – Vererbung basierend auf der Prototypenkette

黄舟
Freigeben: 2017-01-19 15:21:33
Original
1308 Leute haben es durchsucht

Eines der Merkmale der Objektorientierung ist die Vererbung. Die meisten objektorientierten Programmiersprachen unterstützen zwei Arten der Vererbung: Schnittstellenvererbung und Implementierungsvererbung. Die Schnittstellenvererbung erbt nur Methodensignaturen, während die Implementierungsvererbung die tatsächlichen Methoden erbt. Da Funktionen in JavaScript keine Signaturen haben, kann die Schnittstellenvererbung nicht implementiert werden. In JavaScript wird die Vererbung hauptsächlich über die Prototypenkette implementiert.

Vererbung basierend auf der Prototypenkette implementieren

Die Grundidee der Implementierung der Vererbung basierend auf der Prototypenkette besteht darin, Prototypen zu verwenden, um einem Referenztyp die Eigenschaften und Methoden eines anderen Referenztyps erben zu lassen. Zuvor haben wir die Beziehung zwischen Prototypen, Konstruktoren und Objektinstanzen vorgestellt und deren Speichermodellstrukturen im Detail analysiert. Anhand des folgenden Beispiels analysieren wir, wie JavaScript die Vererbung basierend auf der Prototypenkette implementiert.

// 创建父类
function Parent(){
  this.parentValue = "Parent";
}
// 在父类的原型中添加方法
Parent.prototype.showParentValue = function(){
  alert(this.parentValue);
}
 
// 创建子类
function Child(){
  this.childValue ="Child";
}
// 实现继承,让子类Child的原型链指向Parent对象
Child.prototype = new Parent();
 
// 在子类的原型中添加方法
Child.prototype.showChildValue = function(){
  alert(this.childValue);
}
 
// 创建子类对象
var c = new Child();
 
// 子类对象调用继承自父类的方法
c.showParentValue();
 
// 子类对象调用自己的方法
c.showChildValue();
Nach dem Login kopieren

Im obigen Code erstellen wir zunächst eine übergeordnete Klasse Parent und fügen ihrem Prototyp die Methode showParentValue hinzu.

Dann haben wir eine Unterklasse Child erstellt und die Vererbung implementiert, indem wir die Prototypenkette der Unterklasse auf die übergeordnete Klasse verweisen ließen.

/** 实现继承的关键代码 **/Child.prototype = new Parent();
Nach dem Login kopieren

Fügen Sie dann die Methode showChildValue zur Prototypenkette der Unterklasse hinzu. Anschließend wird ein Unterklassenobjekt erstellt. Zu diesem Zeitpunkt kann das Unterklassenobjekt c seine eigenen Methoden oder von der übergeordneten Klasse geerbten Methoden aufrufen.

Nach der Ausführung des obigen Codes sieht das Speichermodelldiagramm der Unterklasse und der übergeordneten Klasse wie folgt aus:

JavaScript objektorientiert – Vererbung basierend auf der Prototypenkette

Wie wir auf dem obigen Bild sehen können Beim Erstellen einer Unterklasse zeigt das Prototypattribut der Unterklasse auf das Prototypobjekt der Unterklasse. Wenn wir den Prototyp der Unterklasse über die Anweisung Child.prototype = new Parent(); auf das übergeordnete Klassenobjekt verweisen lassen, schreiben wir tatsächlich das Prototypobjekt der Unterklasse neu. Zu diesem Zeitpunkt gibt es im Prototypobjekt der Unterklasse ein _proto_-Attribut, das auf das Prototypobjekt der übergeordneten Klasse verweist. Das ursprüngliche Prototypobjekt der Unterklasse (roter Bereich im Bild) ist tatsächlich nutzlos.

Die Methoden, die wir im Unterklassen-Prototyp hinzufügen, werden dann dem neuen Unterklassen-Prototyp hinzugefügt. Gleichzeitig werden die Attribute der übergeordneten Klasse auch in den neuen Unterklassen-Prototyp geschrieben.

Nachdem wir das Unterklassenobjekt c erstellt haben, rufen wir über das Objekt c die showParentValue-Methode der übergeordneten Klasse auf. Wenn Objekt c diese Methode nicht in seinem eigenen Bereich findet, sucht es im Prototyp der Unterklasse über das Attribut _proto_. Es findet diese Methode ebenfalls nicht und geht dann über das Attribut _proto_ zum Prototyp der übergeordneten Klasse. Attribut im Prototyp zu suchen, zu diesem Zeitpunkt wird die Methode showParentValue gefunden und korrekt ausgeführt.

Der obige Prozess ist der Prozess der Implementierung der Vererbung basierend auf der Prototypenkette.

Vollständiges Speichermodell basierend auf einer Prototypenkette zur Implementierung der Vererbung

Im obigen Speichermodell basierend auf einer Prototypenkette zur Implementierung der Vererbung beschreiben wir tatsächlich ein Objekt weniger: Objekt. Alle Referenztypen erben von Object, und diese Vererbung wird auch über die Prototypenkette implementiert. Daher ist das vollständige Speichermodell, das auf der Prototypkette zur Implementierung der Vererbung basiert, wie folgt:

JavaScript objektorientiert – Vererbung basierend auf der Prototypenkette

Der Standardprototyp aller Funktionen ist Object, daher enthält der Standardprototyp eine Interner Zeiger, der auf Object.prototype zeigt. Es gibt integrierte Methoden hasOwnProperty, isPrototypeOf, propertyEmunerable, toLocaleString, toString und valueOf in Object.prototype, sodass unsere benutzerdefinierten Typen diese Methoden erben.

Dinge, die bei der Verwendung der Prototypenkette zur Vererbung zu beachten sind

Wenn Sie die Prototypenkette zur Vererbung verwenden, achten Sie bitte auf die folgenden Punkte:

  • 1. Es kann nicht verwendet werden. Weisen Sie die Prototypenkette nach dem Festlegen der Prototypenkette neu zu.

  • 2. Methoden müssen nach der Zuweisung in der Prototypenkette hinzugefügt oder überschrieben werden.

Für den ersten Punkt schauen wir uns das folgende Beispiel an:

function Parent(){
  this.parentValue = "Parent";
}
Parent.prototype.showParentValue = function(){
  alert(this.parentValue);
}
function Child(){
  this.childValue ="Child";
}
//实现继承,让Child的原型链指向Parent对象
Child.prototype = new Parent();
 
//下面的操作重写了Child的原型
Child.prototype = {
  showChildValue:function(){
    alert(this.value);
  }
}
Nach dem Login kopieren

在上面的代码中,我们分别创建了一个父类和一个子类,并让子类的原型指向父类对象,实现继承。但是在这之后,我们又通过Child.prototype = {...}的方式重写了子类的原型,在原型的重写一文中我们已经讲过,重写原型实际上是使子类的原型重新指向一个新的子类原型,这个新的子类原型和父类之间并没有任何的关联关系,所以子类和父类之间此时不再存在继承关系。

对于第二点也很好理解,也来看一个例子:

function Parent(){
  this.parentValue = "Parent";
}
Parent.prototype.showParentValue = function(){
  alert(this.parentValue);
}
function Child(){
  this.childValue ="Child";
}
 
//在实现继承之前为子类在原型中添加方法
Child.prototype.showChildValue = function(){
  alert(this.childValue);
}
 
//实现继承,让Child的原型链指向Parent对象
Child.prototype = new Parent();
Nach dem Login kopieren

在上面的代码中,我们分别创建了父类和子类。在创建子类之后马上为子类在原型中添加一个方法,然后才让Child的原型链指向Parent对象,实现继承。

这样做的后果是实现继承之后,子类指向的是新的子类原型,而前面添加的方法是放置在原来的原型中的(内存模型图中的红色区域),所以在实现继承之后,子类对象将不再拥有这个方法,因为原来的原型现在已经没有作用了。

方法的覆盖及原型链继承的缺点

如果我们需要实现子类的方法来覆盖父类的方法,只需要在子类的原型中添加与父类同名的方法即可。

/** 覆盖父类中的showParentValue方法 **/
Child.prototype.showParentValue = function(){
  alert("Override Parent method");
}
Nach dem Login kopieren

原型链虽然是否强大,可以实现继承,但是原型链也存在一些缺点。原型链继承的缺点主要有:

  • 1、使用原型链进行继承最大的缺点是无法从子类中调用父类的构造函数,这样就没有办法把子类中的属性赋值到父类中。

  • 2、如果父类中存在引用类型的属性,此时这个引用类型会添加到子类的原型中,当第一个对象修改这个引用之后,其它对象的引用同样会被修改。

原型链和原型在处理引用类型的值的时候存在同样的问题。我们在介绍原型的时候曾经举过一个使用引用类型的例子。在使用原型链时同样会有这个问题。来看下面的例子:

// 创建父类
function Parent(){
  this.parentValue = "Parent";
  //引用类型的属性
  this.friends = ['Leon','Ada'];
}
// 在父类的原型中添加方法
Parent.prototype.showParentValue = function(){
  console.info(this.name+"["+this.friends+"]");
}
 
// 创建子类
function Child(){
  this.childValue ="Child";
}
// 实现继承,让子类Child的原型链指向Parent对象
Child.prototype = new Parent();
 
// 在子类的原型中添加方法
Child.prototype.showChildValue = function(){
  console.info(this.name+"["+this.friends+"]");
}
 
// 创建子类对象
var person1 = new Child();
person1.name = "Jack";
person1.friends.push('Tom');
var person2 = new Child();
person2.name = "John";
console.info(person2.friends);
Nach dem Login kopieren

在上面的代码中,在父类中有一个引用类型的数组对象属性friends,在子类实现继承之后,子类对象person1为它的friends添加了一个新的朋友,此时,新的朋友是被添加到父类的原型中的,所以在这之后创建的所有新的对象都会有一个新的朋友“Tom”。这就是引用类型属性存在的问题。

以上就是JavaScript面向对象-基于原型链实现继承的内容,更多相关内容请关注PHP中文网(www.php.cn)!


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
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!