Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Einführung in die JS-Vererbung (Prototypkette, Konstruktor, Kombination, Prototyp, parasitär, parasitäre Kombination, Klassenerweiterungen)

Detaillierte Einführung in die JS-Vererbung (Prototypkette, Konstruktor, Kombination, Prototyp, parasitär, parasitäre Kombination, Klassenerweiterungen)

不言
不言Original
2018-07-23 10:53:281511Durchsuche

Der Inhalt dieses Artikels besteht darin, Ihnen eine detaillierte Einführung in die JS-Vererbung zu geben (Prototypkette, Konstruktor, Kombination, Prototyp, Parasit, parasitäre Kombination, Klassenerweiterungen) Sie können darauf verweisen dazu.

Um ehrlich zu sein, musste ich früher nur wissen, dass „parasitäre kombinatorische Vererbung“ die beste ist, solange es eine Codevorlage der Vorfahren gab, die ich verwenden konnte. Aufgrund einiger Dinge habe ich in letzter Zeit mehrere Wochen darüber nachgedacht, sie zu klären. Dieser Artikel verwendet den Inhalt von „JavaScript Advanced Programming“ als Grundgerüst, ergänzt den relevanten Inhalt der ES6-Klasse und beschreibt die Vererbung aus einer Perspektive, die meiner Meinung nach leichter zu verstehen ist. Ich hoffe, dass jeder etwas gewinnen kann.

1. Vererbungsklassifizierung

Lassen Sie uns zunächst einen Gesamteindruck vermitteln. Wie in der Abbildung gezeigt, kann die Vererbung in JS in zwei Teile unterteilt werden, je nachdem, ob die Objektfunktion verwendet wird (siehe unten) (Object.create ist eine neue Methode in ES5 zur Standardisierung dieser Funktion).

Unter diesen haben die Prototypenkettenvererbung und die Prototypenvererbung die gleichen Vor- und Nachteile, und auch die Konstruktorvererbung und die parasitäre Vererbung entsprechen einander. Die parasitäre Kombinationsvererbung basiert auf Object.create und optimiert gleichzeitig die Kombinationsvererbung und wird zu einer perfekten Vererbungsmethode. Die Ergebnisse von ES6 Class Extends sind im Grunde die gleichen wie bei der Vererbung parasitärer Kombinationen, die Implementierung unterscheidet sich jedoch geringfügig.

Kommen wir gleich zur Sache.

Detaillierte Einführung in die JS-Vererbung (Prototypkette, Konstruktor, Kombination, Prototyp, parasitär, parasitäre Kombination, Klassenerweiterungen)

2. Vererbungsmethode

Die Prototypkettenvererbung, die Konstruktorvererbung und die Kombinationsvererbung in der oberen Hälfte des Bildes oben haben viel zu bieten Der Inhalt im Internet wird in diesem Artikel nicht im Detail beschrieben, sondern nur auf die wichtigsten Punkte hingewiesen. Hier ist der Artikel „Vererbung in JS (Teil 1)“, der meiner Meinung nach am einfachsten zu verstehen ist. Wenn Sie mit dem Inhalt der ersten Hälfte nicht vertraut sind, können Sie diesen Artikel zuerst lesen und dann zurückkommen, um mit dem Lesen fortzufahren. Wenn Sie damit bereits vertraut sind, können Sie diesen Teil schnell überspringen. Darüber hinaus lehnt sich die erste Hälfte des Abschnitts stark an einen übernommenen Artikel über das yq-Frontend [1] an.

2.1 Prototypische Vererbung

Kern: Verwenden Sie die Instanz der übergeordneten Klasse als Prototyp der untergeordneten Klasse

SubType.prototype = new SuperType() 
// 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向SuperType。
SubType.prototype.constructor = SubType;

Vorteile: Methoden der übergeordneten Klasse können wiederverwendet werden
Nachteile :

  • Die Referenzeigenschaften der übergeordneten Klasse werden von allen Unterklasseninstanzen gemeinsam genutzt

  • Die Unterklasse kann beim Erstellen keine Parameter an die übergeordnete Klasse übergeben eine Instanz

2.2 Konstruktorvererbung

Kern: Kopieren Sie den Inhalt des übergeordneten Klassenkonstruktors in den Unterklassenkonstruktor. Dies ist die einzige Vererbung unter allen Vererbungen, die keinen Prototyp beinhaltet.

SuperType.call(SubType);

Vorteile: Völlig das Gegenteil der Prototypenkettenvererbung.

  • Die Referenzeigenschaften der übergeordneten Klasse werden nicht gemeinsam genutzt

  • Die Unterklasse kann beim Erstellen einer Instanz Parameter an die übergeordnete Klasse übergeben

Nachteile: Die Methoden der übergeordneten Klasse können nicht wiederverwendet werden und die Methoden der Unterklasseninstanz werden jedes Mal separat erstellt.

2.3 Kombinationsvererbung

Kern: Eine Kombination aus Prototypenvererbung und Konstruktorvererbung, die die Vorteile beider vereint.

function SuperType() {
    this.name = 'parent';
    this.arr = [1, 2, 3];
}

SuperType.prototype.say = function() { 
    console.log('this is parent')
}

function SubType() {
    SuperType.call(this) // 第二次调用SuperType
}

SubType.prototype = new SuperType() // 第一次调用SuperType

Vorteile:

  • Die Methoden der übergeordneten Klasse können wiederverwendet werden

  • Die Referenzattribute der übergeordneten Klasse werden wiederverwendet nicht geteilt werden

  • Wenn eine Unterklasse eine Instanz erstellt, kann sie Parameter an die übergeordnete Klasse übergeben

Nachteile:
Der Konstruktor von Die übergeordnete Klasse wird zweimal aufgerufen. Beim ersten Mal werden die Namens- und arr-Attribute der übergeordneten Klasse zum Prototyp der Unterklasse hinzugefügt. Beim zweiten Mal werden die Namens- und arr-Attribute der übergeordneten Klasse zum Konstruktor der Unterklasse hinzugefügt , wodurch die gleichnamigen Parameter im Prototyp der Unterklasse überschrieben werden. Diese Überschreibsituation führt zu einer Leistungsverschwendung.

2.4 Prototypische Vererbung

Kern: Die Objektmethode der prototypischen Vererbung ist im Wesentlichen eine flache Kopie des Parameterobjekts.
Vorteile: Methoden der übergeordneten Klasse können wiederverwendet werden
Nachteile:

  • Die Referenzeigenschaften der übergeordneten Klasse werden von allen Unterklasseninstanzen gemeinsam genutzt

  • Die Unterklasse kann beim Erstellen einer Instanz keine Parameter an die übergeordnete Klasse übergeben

function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
ECMAScript 5 standardisiert die prototypische Vererbung durch die neue Methode Object.create(). Diese Methode akzeptiert zwei Parameter: ein Objekt, das als Prototyp des neuen Objekts verwendet wird, und (optional) ein Objekt zum Definieren zusätzlicher Eigenschaften für das neue Objekt. Die Methode Object.create() verhält sich genauso wie die Methode object(), wenn ein Parameter übergeben wird. ——"JAVASCript Advanced Programming"

So kann der obige Code in

var yetAnotherPerson = object(person); => var yetAnotherPerson = Object.create(person);

2.5 Parasitäre Vererbung

Kern: Verwenden Sie die prototypische Vererbung, um eine flache Kopie des Ziels zu erhalten object und verbessern Sie dann die Fähigkeit dieser flachen Kopie.
Vor- und Nachteile: Bietet nur eine Idee, keine Vorteile

function createAnother(original){ 
    var clone=object(original);    //通过调用函数创建一个新对象
    clone.sayHi = function(){      //以某种方式来增强这个对象
        alert("hi");
    };
    return clone;                  //返回这个对象
}

var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

2.6 Parasitäre Kombinationsvererbung

Wie gerade erwähnt, ruft eine der Kombinationsvererbungen den Konstruktor der übergeordneten Klasse zweimal auf , was verschwenderisch ist Nachteile, parasitäre Kombinationsvererbung kann dieses Problem lösen.

function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); // 创建了父类原型的浅复制
    prototype.constructor = subType;             // 修正原型的构造函数
    subType.prototype = prototype;               // 将子类的原型替换为这个原型
}

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    alert(this.name);
};

function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
// 核心:因为是对父类原型的复制,所以不包含父类的构造函数,也就不会调用两次父类的构造函数造成浪费
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}

Vor- und Nachteile: Dies ist eine perfekte Art zu erben.

2.7 ES6-Klassenerweiterungen

Kern: Die Ergebnisse der ES6-Vererbung ähneln der parasitären kombinierten Vererbung. Im Wesentlichen ist die ES6-Vererbung eine Art syntaktischer Zucker. Die parasitäre kombinierte Vererbung erstellt jedoch zunächst das Objekt dieser Unterklasse und erweitert es dann, während ES6 zunächst die Attribute und Methoden des Instanzobjekts der übergeordneten Klasse hinzufügt (daher muss zuerst die Super-Methode aufgerufen werden) und dann das Objekt verwendet Unterklasseninstanzobjekt zu Der Konstruktor der Klasse ändert dies.

class A {}

class B extends A {
  constructor() {
    super();
  }
}

Das spezifische Prinzip der Vererbung in ES6:

class A {
}

class B {
}

Object.setPrototypeOf = function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);

ES6继承与ES5继承的异同:
相同点:本质上ES6继承是ES5继承的语法糖
不同点:

  • ES6继承中子类的构造函数的原型链指向父类的构造函数,ES5中使用的是构造函数复制,没有原型链指向。

  • ES6子类实例的构建,基于父类实例,ES5中不是。

3. 总结

  • ES6 Class extends是ES5继承的语法糖

  • JS的继承除了构造函数继承之外都基于原型链构建的

  • 可以用寄生组合继承实现ES6 Class extends,但是还是会有细微的差别

相关推荐:

Vue中钩子函数的具体介绍

AngularJs自定义指令可以如何来设置以及自定义指令的命名规范

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in die JS-Vererbung (Prototypkette, Konstruktor, Kombination, Prototyp, parasitär, parasitäre Kombination, Klassenerweiterungen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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