Heim  >  Artikel  >  Web-Frontend  >  Zusammenfassung der Dinge, auf die Sie in der Javascript-Prototypkette achten sollten

Zusammenfassung der Dinge, auf die Sie in der Javascript-Prototypkette achten sollten

不言
不言nach vorne
2018-10-20 15:59:551601Durchsuche

Dieser Artikel bietet Ihnen eine Zusammenfassung dessen, worauf Sie in der JavaScript-Prototypenkette achten müssen. Ich hoffe, dass er für Freunde hilfreich ist.

Vorwort: Ich habe kürzlich „Javascript Advanced Programming“ gelesen. Für mich sind die Übersetzungen der chinesischen Version des Buches an vielen Stellen unbefriedigend, daher versuche ich, es mit dem zu interpretieren, was ich verstehe. Sollten Fehler oder Auslassungen vorliegen, sind wir Ihnen sehr dankbar, wenn Sie uns darauf hinweisen. Der größte Teil des Inhalts in diesem Artikel stammt aus „JavaScript Advanced Programming, Third Edition“

1. Vergessen Sie nicht den Standardprototyp

Eigentlich der Prototyp Im vorherigen Beispiel gezeigte Kette. Ein Glied fehlt.

Wir alle wissen, dass alle Referenztypen standardmäßig Object erben und diese Vererbung auch über die Prototypenkette implementiert wird.

Der Standardprototyp aller Funktionen ist eine Instanz von Object. Denn das Prototypobjekt einer Funktion ist auch ein Objekt! Das Objekt ist natürlich eine Instanz von Object!

Daher enthält der Prototyp der Funktion einen internen Zeiger (__proto__), der auf Object.prototype zeigt.

Dies ist auch der grundlegende Grund, warum alle benutzerdefinierten Typen Standardmethoden wie toString() und valueOf() erben.

Die Prototypenkette des im vorherigen Beispiel gezeigten Prototyps sollte also auch eine weitere Vererbungsebene enthalten.

Der folgende Code zeigt diese vollständige Prototypenkette.

//完整原型链的伪代码
function Object() {
}
Object.prototype = {
    constructor: f Object(),
    hasOwnProperty: f hasOwnProperty(),
    isPrototypeOf: f isPrototypeOf(),
    propertyIsEnumerable: f propertyIsEnumerable(),
    toLocaleString: f toLocaleString(),
    toString: f toString(),
    valueOf: f valueOf()
}
//SuperType 父类型
function SuperType(){
    this.property = true;
}
SuperType.prototype.getSuperProperty = function() {
    console.log(this.property);
    return this.property;
}
/*
SuperType.prototype = {
    constructor: f SuperType(),
    getSuperProperty: function() {
    console.log(this.property);
    return this.property;
    }, 
    __proto__ : {
        constructor: f Object(),
        hasOwnProperty: f hasOwnProperty(),
        isPrototypeOf: f isPrototypeOf(),
        propertyIsEnumerable: f propertyIsEnumerable(),
        toLocaleString: f toLocaleString(),
        toString: f toString(),
        valueOf: f valueOf()
    }
}
*/
//SubType 子类型
function SubType() {
    this.subproperty = false;
}
//子类型 继承 父类型
SubType.prototype = new SuperType();
//实际上子类型的原型是这样的。
/*SubType.prototype = {
    property: true,
    __proto__:  {
        constructor : SuperType,
        getSuperProperty:function() {
            console.log(this.property);
            return this.property;
        }
    }
}
*/
SubType.prototype.getSubProperty = function(){
    console.log(this.subproperty);
    return this.subproperty;
}
//那么现在子类型的原型对象是这样的
/*SubType.prototype = {
    property: true,
    getSubProperty: function()  {
    console.log(this.subproperty);
    return this.subproperty;
    },
    __proto__:  {
        constructor : SuperType,
        getSuperProperty:function() {
            console.log(this.property);
            return this.property;
        }
    }
}
*/

var subInstanceObject = new SubType();
console.log(subInstanceObject.getSuperProperty()); // true

Kurz gesagt, SubType (Subtyp) erbt SuperType (übergeordneter Typ),

und SuperType (übergeordneter Typ) erbt Object (Vorfahr).

Wenn subInstanceObject.toString() aufgerufen wird, wird tatsächlich die in Object.prototype gespeicherte Methode aufgerufen.

2. Bestimmen Sie die Beziehung zwischen Prototyp- und Instanzobjekten

Die Beziehung zwischen Prototyp und Instanz kann auf zwei Arten bestimmt werden.

Die erste Möglichkeit besteht darin, den Instanzenoperator zu verwenden. Solange die Prototypenkette im erkannten Instanzobjekt einen aufgetretenen Konstruktor enthält, wird das Ergebnis „true“ zurückgeben.
Denn das zeigt, dass sie alle an der Erstellung von Instanzobjekten beteiligt sind.

console.log(subInstanceObject instanceof Object); // true
console.log(subInstanceObject instanceof SuperType); // true
console.log(subInstanceObject instanceof SubType); // true

Aufgrund der Prototypenkette können wir sagen, dass subIntanceObject eine Instanz eines beliebigen Typs zwischen Object, SuperType oder SubType ist.

Die zweite Möglichkeit ist die Verwendung der Methode isPrototypeOf(). Ebenso kann man sagen, dass es sich um den Prototyp des aus der Prototypenkette abgeleiteten Instanzobjekts handelt, solange es sich um einen Prototyp handelt, der in der Prototypenkette erscheint.

console.log(Object.prototype.isPrototypeOf(subInstanceObject)); //true
console.log(SuperType.prototype.isPrototypeOf(subIntanceObject)); // true
console.log(SubType.prototype.isPrototypeOf(subIntanceObject)); //true

3. Definieren Sie Methoden sorgfältig

Untertypen müssen manchmal eine Methode des übergeordneten Typs überschreiben oder eine Methode hinzufügen, die im übergeordneten Typ nicht vorhanden ist.

Aber egal was passiert, der Code, der Methoden zum Prototyp hinzufügt, muss nach der Anweisung platziert werden, die den Prototyp ersetzt.

function SuperType() {
    this.property = true;
}

SuperType.prototype.getSuperValue = function() {
    return this.property;
}

function SubType() {
    this.subproperty = false;
}

//继承了SuperType
SubType.prototype = new SuperType();

//给原型添加方法的代码一定要放在替换原型的语句之后
//添加新方法
SubType.prototype.getSubValue = function() {
    return this.subproperty;
}

//重写 超类型中 的 方法
SubType.prototype.getSuperValue = function() {
    return false;
}

var instance = new SubType();
console.log(instance.getSuperValue())

Im obigen Code wird die erste Methode getSubValue() zu SubType hinzugefügt.
Die zweite Methode getSuperValue() ist eine Methode, die bereits im Prototyp vorhanden ist.
Das Überschreiben dieser Methode führt dazu, dass der Prototyp der Unterklasse seine eigene getSuperValue()-Methode findet.
Wenn getSuperValue() über das SuperType-Instanzobjekt aufgerufen wird, wird weiterhin die ursprüngliche Methode aufgerufen.

Ich betone noch einmal, dass zwei Methoden definiert werden müssen, nachdem der Prototyp durch ein Instanzobjekt von SuperType ersetzt wurde.

Eine weitere Sache, die zu beachten ist, ist, dass bei der Implementierung der Vererbung über die Prototypkette keine Objektliterale zum Erstellen von Prototypmethoden verwendet werden können. Dadurch wird die Prototypenkette neu geschrieben.

function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
}

function SubType(){
    this.subproperty = false;
}

//继承SuperType
SubType.prototype = new SuperType();

/* 
现在的原型
SubType.prototype = {

    property: true,
    __proto__: {
        constructor: SuperType,
        getSuperValue: function() {
            return this.property;
        }
    }
}
*/

//使用对象字面量语法会改写原型,导致上一行代码无效
// SubType.prototype = new Object();
SubType.prototype = {

    getSubValue: function() {
        return this.subproperty;
    },

    someOtherMethod: function () {
        return false;
    }

    /*,
    __proto__ : {
        constructor: fn Object(),
        .......
    }
    */

}

var instance =  new SubType();
console.log(instance.getSuperValue()); // error: instance.getSuperValue is not a function

Der obige Code zeigt das Problem, das durch die einfache Zuweisung des Instanzobjekts von SuperType zum Prototyp und das anschließende Ersetzen des Prototyps durch ein Objektliteral verursacht wird.

Da der Prototyp von SubType tatsächlich eine Instanz von Object anstelle eines Instanzobjekts von SuperType speichert, ist diese Kette unterbrochen.

4. Probleme mit der Prototypenkette

Obwohl die Prototypenkette sehr leistungsfähig ist und zur Implementierung der Vererbung verwendet werden kann, weist sie immer Mängel auf. Es gibt keine perfekte Methode in der Welt.

Das Hauptproblem entsteht durch Prototypen, die Referenztypwerte enthalten.

Prototypeigenschaften, die Referenztypwerte enthalten, werden von allen Instanzobjekten gemeinsam genutzt.

Und genau aus diesem Grund werden Prototypenmuster und Konstruktormuster in Kombination verwendet.
Definieren Sie Eigenschaften im Konstruktormuster und definieren Sie gemeinsam genutzte Methoden im Prototypmuster.

Bei der Implementierung der prototypischen Vererbung über einen Prototyp wird der Prototyp tatsächlich zu einem Instanzobjekt eines anderen Typs.

Die ursprünglichen Instanzobjekteigenschaften sind zu den aktuellen Prototypeigenschaften geworden.

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

function SubType() {
}

// 子类型继承父类型
SubType.prototype = new SuperType();

/*
SubType.prototype = {
    colors: ['red', 'green', 'blue'],
    __proto__: {
        constructor: fn SuperType(),
        .....
    }
}
*/

var instance1 = new SubType();

instance1.colors.push('black');

console.log(instance1.colors); // ['red', 'green', 'blue', 'black']

var instance2 = new SubType();

console.log(instance2.colors); // ['red', 'green', 'blue', 'black']

Das zweite Problem mit der Prototypenkette besteht darin, dass es keine Möglichkeit gibt, Parameter an den Konstruktor des übergeordneten Typs zu übergeben, ohne alle Instanzobjekte zu beeinflussen.

Aufgrund der beiden oben genannten Probleme wird die Prototypenkette selten allein bei Veranstaltungen verwendet.

Das obige ist der detaillierte Inhalt vonZusammenfassung der Dinge, auf die Sie in der Javascript-Prototypkette achten sollten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen