Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung der JS-Vererbung

Detaillierte Erläuterung der JS-Vererbung

php中世界最好的语言
php中世界最好的语言Original
2018-03-13 17:31:301260Durchsuche

Dieses Mal werde ich Ihnen eine detaillierte Erklärung zur JS-Vererbung geben. Was sind die Vorsichtsmaßnahmen bei der Verwendung der JS-Vererbung? Hier sind praktische Fälle.

ECMAScript implementiert die Vererbung auf mehr als eine Weise. Dies liegt daran, dass der Vererbungsmechanismus in JavaScript nicht explizit spezifiziert, sondern durch Nachahmung implementiert wird. Dies bedeutet, dass nicht alle Vererbungsdetails vollständig vom Interpreter behandelt werden. Sie können die geeignete Vererbungsmethode entsprechend Ihren Anforderungen festlegen.

Objektidentitätswechsel

KonstruktorVerwenden Sie dieses Schlüsselwort, um allen Eigenschaften und Methoden Werte zuzuweisen (d. h. mithilfe des Konstruktors). Methode der Klassendeklaration). Da der Konstruktor nur eine Funktion ist, können Sie den ClassA-Konstruktor zu einer Methode von ClassB machen und diese dann aufrufen. ClassB erhält die im Konstruktor von ClassA definierten Eigenschaften und Methoden.

function ClassA(name) {    this.name = name;    this.sayName = function () {        console.log(this.name);
    };
}function ClassB(name,age) {    this.classA = ClassA;    this.classA(name);    delete this.classA;    this.age = age;    this.sayAge = function(){        console.log(this.age);
    }
}var tom = new ClassA('Tom');var jerry = new ClassB('Jerry',25);
tom.sayName();                         //'Tom'jerry.sayName();                       //'Jerry'jerry.sayAge();                        //25console.log(tom instanceof ClassA);    //trueconsole.log(jerry instanceof ClassA);  //falseconsole.log(jerry instanceof ClassB);  //true

Alle neuen Eigenschaften und neuen Methoden müssen nach dem Löschen der Codezeile der neuen Methode definiert werden, da die zugehörigen Eigenschaften und Methoden der Superklasse möglicherweise überschrieben werden

Objektidentitätswechsel kann Mehrfachvererbung erreichen
Wenn ClassA und ClassB vorhanden sind, möchte ClassC diese beiden Klassen wie folgt erben:

function ClassA(name){    this.name = name;    this.sayName = function (){        console.log(this.name);
    }
}function ClassB(age){    this.age = age;    this.sayAge = function(){        console.log(this.age);
    }
}function ClassC(name,age){    this.method = ClassA;    this.method(name);    
    this.method = ClassB;    this.method(age);    delete this.method;
}var tom = new ClassC('Tom',25);
tom.sayName();                       //'Tom';tom.sayAge();                        //25console.log(tom instanceof ClassA);  //falseconsole.log(tom instanceof ClassB);  //falseconsole.log(tom instanceof ClassC);  //true

Der Fehler dieser Implementierung ist: Wenn die beiden Klassen ClassA und ClassB Attribute mit haben Hat KlasseB denselben Namen oder dieselbe Methode, hat sie eine hohe Priorität, da sie von der späteren Klasse erbt.
Aufgrund der Beliebtheit dieser Vererbungsmethode fügte die dritte Version von ECMAScript dem Function-Objekt zwei Methoden hinzu, nämlich call() und apply().

Die Aufrufmethode ist der klassischen Objektidentitätsmethode am ähnlichsten. Sein erster Parameter wird als Objekt davon verwendet, und andere Parameter werden direkt an die Funktion selbst übergeben

function sayName(prefix) {    console.log(prefix + this.name);
};var tom = {};
tom.name = "Tom";
sayName.call(tom, 'This is ');  //'This is Tom'

Die Funktion sayName wird außerhalb des Objekts definiert, kann aber auch darauf verweisen.
Die Aufrufmethode schreibt das Objekt so um, dass es sich ausgibt.

function ClassA(name){    this.name = name;    this.sayName = function(){        console.log(this.name);    }}function ClassB(name,age){    //this.method = ClassA;    //this.method(name);    //delete this.method;    ClassA.call(this,name);    this.age = age;    this.sayAge = function (){        console.log(this.age);    }}var tom = new ClassB('Tom',25);tom.sayName();                       //'Tom'tom.sayAge();                        //25console.log(tom instanceof ClassA);  //falseconsole.log(tom instanceof ClassB);  //true

Die Aufrufmethode ersetzt die Art und Weise, Attribute zum Referenzieren von ClassA zu verwenden.

apply

Die apply-Methode hat zwei Parameter, das als Objekt verwendete Objekt und die Parameter, die an die -Funktion array

function sayName(prefex,mark) {    console.log(prefex+ this.name+ mark);
};var tom = {};
tom.name = 'Tom';
sayName.apply(tom, ['This is ','!']);  //'This is Tom!'
übergeben werden sollen

Sie können „Apply“ auch verwenden, um das Objekt neu zu schreiben, das es imitieren soll

function ClassA(name){    this.name = name;    this.sayName = function(){        console.log(this.name);    }}function ClassB(name,age){    ClassA.apply(this,arguments);    this.age = age;    this.sayAge = function (){        console.log(this.age);    }}var tom = new ClassB('Tom',25);tom.sayName();                       //'Tom'tom.sayAge();                        //25  console.log(tom instanceof ClassA);  //falseconsole.log(tom instanceof ClassB);  //true

Das Parameterarray kann nur übergeben werden, wenn die Reihenfolge der Parameter in der Superklasse vollständig mit den Parametern in der Unterklasse übereinstimmt

Prototypkette

Das Prototypobjekt ist eine Vorlage. Die zu instanziierenden Objekte basieren auf dieser Vorlage. Alle Attribute und Methoden des Prototypobjekts werden an alle Instanzen dieser Klasse übergeben. Die Prototypkette verwendet diese Funktion, um den Vererbungsmechanismus zu implementieren.

function ClassA() {}ClassA.prototype.name = 'Tom';ClassA.prototype.sayName = function () {    console.log(this.name);};function ClassB() {}ClassB.prototype = new ClassA();var tom = new ClassB();tom.sayName();                       //'Tom'console.log(tom instanceof ClassA);  //trueconsole.log(tom instanceof ClassB);  //true

Hier wird das Prototypattribut von KlasseB als Instanz von KlasseA bezeichnet, um zu vermeiden, dass Prototypattribute einzeln zugewiesen werden.
Beim Aufruf von ClassA werden keine Parameter festgelegt, da der Konstruktor in der Prototypenkette parameterlos sein muss.
In der Prototypenkette hat sich auch das Ergebnis von „instanceof“ geändert und gibt sowohl für ClassA als auch für ClassB „true“ zurück.

Aufgrund der Neuzuweisung von Prototypattributen müssen nach der Zuweisung des Prototyps neue Attribute in der Unterklasse erscheinen.

function ClassA() {}ClassA.prototype.name = 'Tom';ClassA.prototype.sayName = function () {    console.log(this.name);};function ClassB() {}ClassB.prototype = new ClassA();ClassB.prototype.age = 25;ClassB.prototype.sayAge = function () {    console.log(this.age);};var tom = new ClassA();var jerry = new ClassB();tom.sayName();                         //'Tom'jerry.sayName();                       //'Tom'jerry.name = 'Jerry';tom.sayName();                         //'Tom'jerry.sayName();                       //'Jerry'jerry.sayAge();                        //25console.log(tom instanceof ClassA);    //trueconsole.log(jerry instanceof ClassA);  //trueconsole.log(jerry instanceof ClassB);  //true

Der Fehler der Prototypenkette besteht darin, dass eine Mehrfachvererbung nicht erreicht werden kann, da der Prototyp der Klasse neu geschrieben wird.

Gemischte Methode

Das Problem beim Objektidentitätswechsel besteht darin, dass die Konstruktormethode verwendet werden muss und der Konstruktor mit Parametern nicht mithilfe der Prototypenkette verwendet werden kann. Sie können es jedoch versuchen kombiniere beides.
Verwenden Sie Objekte, um vorzutäuschen, die Eigenschaften des Konstruktors zu erben, und verwenden Sie die Prototypenkette, um die Methoden des Prototyps zu erben.

function ClassA(name) {    this.name = name;
}
ClassA.prototype.sayName = function () {    console.log(this.name);
};function ClassB(name, age) {
    ClassA.call(this, name);    this.age = age;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayAge = function () {    console.log(this.age);
};var tom = new ClassA('Tom');var jerry = new ClassB('Jerry',25);console.log(tom instanceof ClassA);                    //trueconsole.log(jerry instanceof ClassA);                  //trueconsole.log(jerry instanceof ClassB);                  //trueconsole.log(jerry.constructor === ClassA);             //trueconsole.log(ClassB.prototype.constructor === ClassA);  //true

Im ClassB-Konstruktor wird das Objekt verwendet, um das Namensattribut von ClassA zu imitieren, und die Prototypkette wird verwendet, um die sayName-Methode von ClassA zu erben Verwendung der Prototypenkettenvererbung, Instanz von Der Betriebsmodus ist normal.
Das Konstruktorattribut stellt jedoch ein Problem dar. Jedes Prototypobjekt verfügt über ein Konstruktorattribut, das auf seinen Konstruktor verweist, der Konstruktor der ClassB-Instanz zeigt jedoch auf ClassA, was zu Verwirrung in der Vererbungskette führt. Sie können den Zeiger des Konstruktors manuell ändern.

function ClassA(name) {    this.name = name;
}
ClassA.prototype.sayName = function () {    console.log(this.name);
};function ClassB(name, age) {
    ClassA.call(this, name);    this.age = age;
}
ClassB.prototype = new ClassA();
ClassB.prototype.constructor = ClassB;
ClassB.prototype.sayAge = function () {    console.log(this.age);
};var tom = new ClassA('Tom');var jerry = new ClassB('Jerry',25);console.log(tom instanceof ClassA);                    //trueconsole.log(jerry instanceof ClassA);                  //trueconsole.log(jerry instanceof ClassB);                  //trueconsole.log(ClassA.constructor === ClassB);            //falseconsole.log(jerry.constructor === ClassA);             //falseconsole.log(ClassB.prototype.constructor === ClassA);  //false

Prototypkette direkt erben

Um Speicher zu sparen, können Sie keine ClassA-Instanz erstellen und den Prototyp von ClassB direkt auf den Prototyp von ClassA verweisen

function ClassA(name) {    this.name = name;
}
ClassA.prototype.sayName = function () {    console.log(this.name);
};function ClassB(name, age) {
    ClassA.call(this, name);    this.age = age;
}
ClassB.prototype = ClassA.prototype;
ClassB.prototype.constructor = ClassB;
ClassB.prototype.sayAge = function () {    console.log(this.age);
};var tom = new ClassA('Tom');var jerry = new ClassB('Jerry',25);console.log(ClassA.prototype.hasOwnProperty('sayAge'));  //trueconsole.log(ClassA.prototype.constructor === ClassB);   //true

So Der Fehler besteht darin, dass sich die Attribute in der ClassB-Prototypkette aufgrund der direkten Änderung des Prototypkettenzeigers auch auf ClassA auswirken, sodass ClassA über die sayAge-Methode verfügt und das Konstruktorattribut von ClassA ClassB ist.

Leeres Objekt als Vermittler

Um die Mängel der direkten Vererbung der Prototypenkette zu beheben, kann ein leeres Objekt als Vermittler verwendet werden.

function ClassA(name) {    this.name = name;
}
ClassA.prototype.sayName = function () {    console.log(this.name);
};function ClassB(name, age) {
    ClassA.call(this, name);    this.age = age;
}var fn = function(){};
fn.prototype = ClassA.prototype;
ClassB.prototype = new fn();
ClassB.prototype.constructor = ClassB;
ClassB.prototype.sayAge = function () {    console.log(this.age);
};console.log(ClassA.prototype.hasOwnProperty('sayAge'));  //falseconsole.log(ClassA.prototype.constructor === ClassB);    //false

Obwohl die Objektinstanz noch erstellt wird, hat das Ändern des Prototyps von ClassB keine Auswirkungen auf ClassA, da das leere Objekt fast keinen Speicher beansprucht.

Eingebettet in die Extensions-Methode

function extends(child,parent){    var fn = function (){};
    fn.prototype = parent.prototype;
    child.prototype = new fn();
    child.prototype.constructor = child;
    child.super = parent.prototype;
}

Die Flexibilität von JS ermöglicht es uns, die Vererbung auf verschiedene Arten zu implementieren. Das Verständnis der Prinzipien und der Implementierung kann uns bei der Auswahl der geeigneten Methode in verschiedenen Szenarien helfen Verfahren.

Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website!

Empfohlene Lektüre:

Verwenden von JS-Code zum Erstellen von Sperreffekten

Verwenden von H5-Canvas zum Erstellen von Sperreffekten

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der JS-Vererbung. 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