Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erklärung der Prototypenkette in JS

Detaillierte Erklärung der Prototypenkette in JS

小云云
小云云Original
2018-03-22 17:19:081740Durchsuche


Obwohl JS keine objektorientierte Sprache ist, bedeutet dies nicht, dass JS keine OOP-Funktionen implementieren kann. Ich glaube, wenn Sie JS verwenden, müssen Sie die Prototypmethoden von Object wie Call, Apply, HasOwnProperty usw. verwendet haben, aber woher kommen diese Methoden? Wenn JS die Vererbung nicht implementieren kann, ist die Verwendung dieser Methoden unmöglich. Hier werden wir über die Methode zur Implementierung der Vererbung in JS, der Prototypenkette, sprechen.

_Proto_ und Prototyp

Zuerst müssen wir verstehen, was ein normales Objekt und was ein Funktionsobjekt ist.

  • Gemeinsames Objekt

    • var a = {}

    • var a = new Object();

    • var a = new f1();//Gleiche wie die vorherige Objekterstellungsmethode

  • Funktionsobjekt

    • var a = function(){};

    • var a = new Function() { };

    • f1()

_proto_ ist ein Attribut, das jedem gewöhnlichen Objekt gehört und zum Verweisen auf den Konstruktor des Prototyps verwendet wird ist das Prototypobjekt des Konstruktors. Das Prototypobjekt des Konstruktors ist im Allgemeinen ein gewöhnliches Objekt (Wenn der Konstruktor eine Funktion ist, wird er zu einem Funktionsobjekt), daher verfügt es auch über das _proto_-Attribut. Und sein _Proto_ zeigt auf das Prototypobjekt seines Konstruktors, nämlich Object.prototype. Das letzte Object.prototype._proto_ zeigt auf null und erreicht die Spitze der Prototypenkette.
Prototyp ist ein Attribut, das Funktionsobjekten gehört. Es wird einer neuen Objektinstanz zugewiesen, wenn das Objekt erstellt wird. Natürlich kann es auch dynamisch geändert werden.

   function Person(){};   var p = new Person();//创建一个普通对象
   //创建过程实际为
   var p={};
   p._proto_=Person.prototype;
   Person.apply(p,arguments);//或者是call...
   //执行构造函数,并返回创建的对象。

Ergänzende Erklärung für den obigen Code

Normalerweise ist es nicht erforderlich, eine Return-Anweisung im Konstruktor zu schreiben, da dieser standardmäßig das neu erstellte Objekt zurückgibt . Wenn jedoch eine Return-Anweisung in den Konstruktor geschrieben wird und die Rückgabe ein Objekt ist, überschreibt die Funktion das neu erstellte Objekt und gibt dieses Objekt zurück, wenn die Rückgabe ein Basistyp wie eine Zeichenfolge, eine Zahl oder ein boolescher Wert ist. usw., dann ignoriert die Funktion die Return-Anweisung oder gibt das neu erstellte Objekt zurück.

Der Standardwert des Prototypobjekts des Konstruktors ist:

  Person.prototype={
    constructor://指向构造函数本身
    _proto_://指向构造函数Person的原型对象的构造函数的原型对象,这里是指Object.prototype
  }
  //这里有一个特殊情况——当构造函数为Function的时候
  Function.prototype._proto_===Object.prototype 
  //我们知道Function.prototype是一个函数对象,它的_proto_应该指向它的构造函数的原型,也就是Function.prototype。
  //可是这样下去就没完没了了,毕竟一条链总是有顶端的。这里约定Function.prototype._proto_===Object.prototype;  //这时,Object.prototype._proto_===null;完美结束原型链。

Wir können die Ausrichtung des Prototypobjekts des Konstruktors kontinuierlich ändern, sodass eine Kette schließlich erstellt werden kann gebildet werden. Die oben erwähnte Kette ist die Standard-Prototypkette in JS.

Lassen Sie uns über die Code-Implementierung sprechen

Lassen Sie uns einen Blick auf den Code werfen:

  function Parent(name){
        this.name=name||"parent";
    }    function Son(name){
        this.name=name||"son";        this.property="initial Son name";
    }    function Grandson(name){
        this.name=name||"grandson";        this.ggs="initial Grandson name";
    }

    Son.prototype = new Parent("原型中的Parent");
    Grandson.prototype = new Son("原型中的Son");    let grandson = new Grandson("孙子");
    console.log(grandson instanceof Son);//true
    console.log(grandson instanceof Grandson);//true
    console.log(grandson instanceof Parent);//true

Detaillierte Erklärung der Prototypenkette in JS
Wahr ist am Ende natürlich die Ausgabe. Aber lassen Sie uns ein wenig Code ändern:

    Grandson.prototype = new Son("原型中的Son");
    Son.prototype = new Parent("原型中的Parent");//其实上一步已经实例化了一个Son的对象给Grandson.prototype
    //这个时候Son的实例的_proto_已经确定指向那个时候的构造函数.prototype了(默认原型对象)
    let grandson = new Grandson("孙子");
    console.log(grandson instanceof Son);//false
    console.log(grandson instanceof Grandson);//true
    console.log(grandson instanceof Parent);//false

Detaillierte Erklärung der Prototypenkette in JS
Warum ändert sich das Ergebnis? Der Grund ist auch sehr einfach. Wir haben den Erstellungsprozess der Objekterstellung bereits erwähnt: Wenn das Objekt instanziiert wird, wurde der Prototyp des Konstruktors dem _proto_ des Objekts zugewiesen. Das heißt, der Wert von Grandson.prototype._proto_ wurde in der ersten Zeile des obigen Codes bestimmt. Auch wenn Son.prototype in der zweiten Zeile geändert wird, kann der Wert von Grandson.prototype._proto_ nicht geändert werden.

Schlussfolgerung: Die Beziehung der Prototypenkette in JS wird durch _Proto_ und nicht durch Prototyp aufrechterhalten.

Schnelltest

var animal = function(){}; var dog = function(){};

 animal.price = 2000;
 dog.prototype = animal; var tidy = new dog();
 console.log(dog.price) 
 console.log(tidy.price)

Was ist die Ausgabe? Es ist undefiniert und 2000. Lassen Sie es uns analysieren:
Zuerst wissen wir, dass Tier und Hund beide Funktionsobjekte sind. In der vierten Zeile wird das Prototypobjekt Hund in Tier geändert. Dann schauen wir nach unten. console.log(dog.price) Dieser Satz sucht zunächst nach dem Preis des Hundes, und da ist keiner. Dann suchen Sie in der Prototypenkette danach. Wie haben Sie es gefunden? Wir haben bereits erwähnt, dass wir _proto_ verwenden, um zum Prototypobjekt seines Konstruktors zu gelangen. Da dog ein Funktionsobjekt ist, ist das Prototypobjekt seines Konstruktors Function.prototype, eine leere Funktion. Daher wird undefiniert zurückgegeben und das Preisattribut nicht gefunden.
Was ist mit console.log(tidy.price)?
Ordnung ist ein gewöhnliches Objekt. Zunächst suchen wir nach seinem eigenen Attribut Preis, aber es gibt keinen. Gehen Sie über _proto_ zum Prototypobjekt seines Konstruktors, das dog.prototype ist. Da Tidy nach dog.prototype = animal; instanziiert wird, zeigt der Punkt von Tidy._proto_ bereits auf den geänderten Dog.prototype. Das heißt, es zeigt auf ein Tier, das heißt, das Preisattribut kann gefunden werden, sodass 2000 ausgegeben wird.

Alle Eigenschaften und Methoden des Prototypobjekts können als öffentliche (geschützte) Eigenschaften und Methoden der übergeordneten Klasse in Java betrachtet werden. Verwenden Sie dies innerhalb dieser Methoden, um auf die Eigenschaften und Methoden im Konstruktor zuzugreifen. Verfahren. Was den Grund angeht, muss die Bindungsfrage in JS erwähnt werden ... Kurz gesagt, wer auch immer die Funktion aufruft, darauf weist sie hin. Außer Pfeilfunktionen...

Verwandte Empfehlungen:

Detaillierte Erläuterung des JS-Prototyps und der Prototypenkette (1)

Detaillierte Erläuterung des JS-Prototyps und der Prototypenkette (2)

Detaillierte Erläuterung des JS-Prototyps und der Prototypenkette (3)

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung der Prototypenkette in JS. 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