Dieser Artikel vermittelt Ihnen relevantes Wissen über die Vererbung in JavaScript, einschließlich der Vererbung von Prototypketten, der Vererbung geliehener Konstruktoren, der kombinierten Vererbung und der Mehrfachvererbung.
Vererbung der Prototypkette
Prinzip
Das Wesentliche besteht darin, das Prototypobjekt neu zu schreiben und durch eine Instanz eines neuen Typs zu ersetzen. Im folgenden Code sind die Eigenschaften und Methoden, die ursprünglich im SuperType-Instanzobjekt vorhanden waren, jetzt auch in SubType.prototype vorhanden.
Implementierung
function Super(){ this.value = true; } Super.prototype.getValue = function(){ return this.value } function Sub(){}; // Sub继承了Super Sub.prototype = new Super(); Sub.prototype.constructor = Sub; const ins = new Sub(); console.log(ins.getValue()); // true
Sub erbt Super, und die Vererbung wird erreicht, indem eine Super-Instanz erstellt und die Instanz Sub.prototype zugewiesen wird. Alle Eigenschaften und Methoden, die ursprünglich in der Instanz von Super vorhanden waren, sind jetzt auch in Sub.prototype vorhanden. Wie im Bild gezeigt.
Wie Sie dem obigen Bild entnehmen können, wird der von Sub standardmäßig bereitgestellte Prototyp nicht verwendet, sondern es wird ihm ein neuer Prototyp zugewiesen, der eine Instanz von Super ist. Somit verfügt der neue Prototyp nicht nur über die Eigenschaften und Methoden einer Instanz von Super, sondern verweist auch auf den Prototyp von Super. Das Endergebnis sieht so aus: Die Methode
ins=>Sub的原型=>Super的原型
getValue() befindet sich immer noch in Sub.prototype, aber das Wertattribut befindet sich in Sub.prototype. Dies liegt daran, dass value eine Instanzeigenschaft und getValue() eine Prototypmethode ist. Da Sub.prototype nun eine Instanz von Super ist, befindet sich der Wert in dieser Instanz.
Beachten Sie außerdem, dass ins.constructor jetzt auf Super verweist. Dies liegt daran, dass der ursprüngliche Konstruktor in Sub.prototype neu geschrieben wurde.
Nachteile
Private Prototypeigenschaften werden von Instanzen gemeinsam genutzt
Beim Erstellen einer Instanz eines Untertyps können Parameter nicht an den Konstruktor des übergeordneten Typs übergeben werden
Das Hauptproblem bei der Prototypenkette Vererbung: privat Prototypeigenschaften werden von Instanzen gemeinsam genutzt, weshalb Eigenschaften im Konstruktor und nicht im Prototypobjekt definiert werden. Wenn die Vererbung durch Prototypen implementiert wird, wird die Prototypinstanz zu einer Instanz einer anderen Klasse. Daher wurden die ursprünglichen Instanzattribute natürlich zu den aktuellen Prototypattributen.
function Super(){ this.colors = ['red','green','blue']; } Super.prototype.getValue = function(){ return this.colors } function Sub(){}; //Sub继承了Super Sub.prototype = new Super(); const ins1 = new Super(); ins1.colors.push('black'); console.log(ins1.colors);//['red','green','blue','black']; const ins2 = new Sub(); console.log(ins2.colors);//['red','green','blue','black'];
Das zweite Problem mit der Prototypenkette besteht darin, dass beim Erstellen einer Instanz eines Untertyps keine Parameter an den Konstruktor des übergeordneten Typs übergeben werden können. Tatsächlich sollte gesagt werden, dass es keine Möglichkeit gibt, Parameter an den Konstruktor des übergeordneten Typs zu übergeben, ohne dass sich dies auf alle Instanzen auswirkt. In Verbindung mit dem Problem, dass Prototypeigenschaften, die Referenztypwerte enthalten, von allen Instanzen gemeinsam genutzt werden, wird die Prototypkettenvererbung in der Praxis selten allein verwendet.
Achtung: Verwenden Sie Prototypkettenvererbungsmethoden, um Methoden und Untertypen sorgfältig zu definieren. Manchmal müssen Sie eine Methode der übergeordneten Klasse überschreiben oder eine Methode hinzufügen, die in der übergeordneten Klasse nicht vorhanden ist. Aber egal was passiert, der Code, der dem Prototyp Methoden hinzufügt, muss nach der Anweisung platziert werden, die den Prototyp ersetzt.
function Super() { this.colors = ['red', 'green', 'blue']; } Super.prototype.getValue = function() { return this.colors } function Sub() { this.colors = ['black']; }; //Sub继承了Super Sub.prototype = new Super(); //添加父类已存在的方法,会重写父类的方法 Sub.prototype.getValue = function() { return this.colors; } //添加父类不存在的方法 Sub.prototype.getSubValue = function(){ return false; } const ins = new Sub(); //重写父类的方法之后得到的结果 console.log(ins.getValue()); //['black'] //在子类中新定义的方法得到的结果 console.log(ins.getSubValue());//false //父类调用getValue()方法还是原来的值 console.log(new Super().getValue());//['red', 'green', 'blue']
Prinzip
Geliehener Konstruktor (manchmal auch Pseudoklassenvererbung oder klassische Vererbung genannt). Die Grundidee dieser Technik ist recht einfach: Der Konstruktor der übergeordneten Klasse wird innerhalb des Konstruktors der untergeordneten Klasse aufgerufen. Vergessen Sie nicht, dass Funktionen nichts anderes als Objekte sind, die Code in einer bestimmten Umgebung ausführen. Daher können Konstruktoren mithilfe der Methoden apply() und call() auch auf neu erstellten Objekten ausgeführt werden.
Implementierung
function Super() { this.colors = ['red', 'green', 'blue']; } Super.prototype.getValue = function(){ return this.colors; } function Sub(){ //继承了Super Super.call(this);//相当于把构造函数Super中的this替换成了ins实例对象,这样在Super只有定义的私有属性会被继承下来,原型属性中定义的公共方法不会被继承下来 } const ins = new Sub(); console.log(ins.colors);
function B(name){ this.name = name; } function A(){ //继承了B,同时还传递了参数 B.call(this,'ZZ'); //实例属性 this.age = 100; } const p = new A(); alert(p.name);//'ZZ' alert(p.age);//100
Nachteile
Wenn Wenn Sie sich einfach den Konstruktor ausleihen, können Sie die Probleme des Konstruktormusters nicht vermeiden – die Methoden sind alle im Konstruktor definiert, sodass eine Wiederverwendung von Funktionen nicht in Frage kommt. Darüber hinaus sind im Prototyp der übergeordneten Klasse definierte Methoden für die Unterklasse nicht sichtbar, sodass diese Methode selten verwendet wird.
Kombinierte VererbungPrinzip
Kombinierte Vererbung bezieht sich auf ein Vererbungsmuster, das Prototypenverkettung und geliehene Konstruktortechnologie kombiniert, um das Beste aus beiden zu nutzen. Die Idee dahinter besteht darin, die Prototypenkette zu verwenden, um die öffentlichen Eigenschaften und Methoden des Prototyps zu erben, und die privaten Eigenschaften der übergeordneten Klasse durch Ausleihen der Konstruktorvererbung zu erben. Auf diese Weise wird die Wiederverwendung von Funktionen durch die Definition von Methoden im Prototyp der übergeordneten Klasse erreicht, und jede Instanz verfügt garantiert über die privaten Eigenschaften der übergeordneten Klasse.
Erreichtfunction Super(name){ this.name = name; this.colors = ['red','blue','green']; } Super.prototype.sayName = function(){ alert(this.name); } function Sub(name,age){ Super.call(this,name); this.age = age; } // 继承方法 Sub.prototype = new Super(); Sub.prototype.constructor = Sub; Sub.prototype.sayAge = function(){ alert(this.age); } const ins = new Sub('jarvis',18); ins.colors.push('black'); console.log(ins.colors);// ["red", "blue", "green", "black"] ins.sayName();//'jarvis' ins.sayAge();//18 const ins2 = new Sub('ershiyi',21); console.log(ins2.colors);//["red", "blue", "green"] ins2.sayName();//'ershiyi' ins2.sayAge();//21
在上个例子中,Sub构造函数定义了两个属性:name和age。Super的原型定义了一个sayName()方法。在Sub构造函数中调用Super构造函数时传入了name参数,紧接着又定义它自己的属性age。然后,将Super的实例赋值给Sub的原型,然后又在该新原型上定义了方法sayAge()。这样一来,就可以让不同的Sub实例分别拥有自己的属性——包括colors属性,又可以使用相同的方法组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,称为JavaScript中最常用的继承模式。
缺点
无论在什么情况下,都会调用两次父类的构造函数:一次是在创建子类原型的时候,另一次是在子类构造函数内部。
寄生组合式继承
原理
组合继承是JavaScript最常用的继承模式;不过,它也有自己的不足。组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数:一次是在创建子类原型的时候,另一次是在子类构造函数内部。没错,子类型最终会包含超类型对象的全部实例属性,但不得不在调用子类型构造函数时重写这些属性。再来看一看下面组合继承的例子。
实现
function Super(name){ this.name = name; this.colors = ['red','blue','green']; } Super.prototype.sayName = function(){ alert(this.name); } function Sub(name,age){ Super.call(this,name); this.age = age; } // 继承方法 Sub.prototype = new Super(); Sub.prototype.constructor = Sub; Sub.prototype.sayAge = function(){ alert(this.age); } const ins = new Sub('jarvis',18); ins.colors.push('black'); console.log(ins.colors);// ["red", "blue", "green", "black"] ins.sayName();//'jarvis' ins.sayAge();//18 const ins2 = new Sub('ershiyi',21); console.log(ins2.colors);//["red", "blue", "green"] ins2.sayName();//'ershiyi' ins2.sayAge();//21
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背 后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,所需要的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下所示。
function Super(name){ this.name = name; this.colors = ['red','blue','green']; } Super.prototype.sayName = function(){ alert(this.name); } function Sub(name,age){ //继承实例属性 Super.call(this,name); this.age = age; } // 继承公有的方法 Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.prototype.sayAge = function(){ alert(this.age); } const ins = new Sub('jarvis',18); ins.colors.push('black'); console.log(ins.colors);// ["red", "blue", "green", "black"] ins.sayName();//'jarvis' ins.sayAge();//18 const ins2 = new Sub('ershiyi',21); console.log(ins2.colors);//["red", "blue", "green"] ins2.sayName();//'ershiyi' ins2.sayAge();//21
多重继承
JavaScript中不存在多重继承,那也就意味着一个对象不能同时继承多个对象,但是可以通过变通方法来实现。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>18 多重继承</title> </head> <body> <script type="text/javascript"> // 多重继承:一个对象同时继承多个对象 // Person Parent Me function Person(){ this.name = 'Person'; } Person.prototype.sayName = function(){ console.log(this.name); } // 定制Parent function Parent(){ this.age = 30; } Parent.prototype.sayAge = function(){ console.log(this.age); } function Me(){ // 继承Person的属性 Person.call(this); Parent.call(this); } // 继承Person的方法 Me.prototype = Object.create(Person.prototype); // 不能重写原型对象来实现 另一个对象的继承 // Me.prototype = Object.create(Parent.prototype); // Object.assign(targetObj,copyObj) Object.assign(Me.prototype,Parent.prototype); // 指定构造函数 Me.prototype.constructor = Me; const me = new Me(); </script> </body> </html>
ES5 与 ES6 继承差异
在 ES5 的传统继承中, this 的值会先被派生类创建,随后基类构造器才被调用。这意味着 this 一开始就是派生类的实例,之
后才使用了基类的附加属性对其进行了装饰。
在 ES6 基于类的继承中, this 的值会先被基类创建,随后才被派生类的构造 器所修改。结果是 this 初始就拥有作为基类的内置对象的所有功能,并能正确接收与之关联的所有功能。
【相关推荐:javascript学习教程】
Das obige ist der detaillierte Inhalt vonMachen Sie sich in zehn Minuten mit der JavaScript-Vererbung vertraut. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!