__proto__ VS. Prototyp in JavaScript

785

Diese Abbildung zeigt erneut, dass jedes Objekt einen Prototyp hat. Die Konstruktorfunktion Foo hat auch eine eigene __proto__Funktion, nämlich Function.prototype, und die wiederum über ihre __proto__Eigenschaft erneut auf den Object.prototype verweist. Wiederholen Sie also, Foo.prototype ist nur eine explizite Eigenschaft von Foo, die sich auf den Prototyp von b- und c-Objekten bezieht.

var b = new Foo(20);
var c = new Foo(30);

Was sind die Unterschiede zwischen __proto__und prototype?

Geben Sie hier die Bildbeschreibung ein

Die Figur stammt von dmitrysoshnikov.com .

0x90
quelle
5
Ich denke, Top-Down oder Bottom-Up ist eine Frage der Präferenz. Eigentlich bevorzuge ich es so, damit ich das Diagramm nachverfolgen kann, bis ich herausfinde, woher etwas kommt.
Mike Lippert
1
Mir gefällt, wie JavaScript die prototypische Vererbung verwendet, um den y.constructor in den y .__ proto __. Konstruktor aufzulösen. Mir gefällt auch, wie Object.prototype an der Spitze der prototypischen Vererbungskette steht, wobei Object.prototype .__ proto__ auf null gesetzt ist. Mir gefällt auch, wie das Diagramm eine dreispaltige konzeptionelle Visualisierung erstellt, wie der Programmierer Objekte als 1. Instanzen, 2. Konstruktoren, 3. Prototypen betrachtet, die Konstruktoren diesen Instanzen zuordnen, wenn sie über das neue Schlüsselwort instanziiert werden.
John Sonderson
Diagramm macht sofort Sinn, nachdem Sie etwas wie youtube.com/watch?v=_JJgSbuj5VI , übrigens
mlvljr
Und jetzt, da ich die Antworten gelesen habe, fühle ich mich verpflichtet, das obige Video wirklich zu empfehlen, da es tatsächlich eine kristallklare (und nicht WTFy) Erklärung darüber enthält, was los ist :)
mlvljr

Antworten:

766

__proto__ist das eigentliche Objekt, das in der Suchkette zum Auflösen von Methoden usw. verwendet prototypewird. Ist das Objekt, das zum Erstellen verwendet wird, __proto__wenn Sie ein Objekt erstellen mit new:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
Mark Kahn
quelle
239
Ah! Ist prototypealso nicht für die Instanzen selbst (oder andere Objekte) verfügbar, sondern nur für die Konstruktorfunktionen.
Rvighne
43
@rvighne: prototypeist nur für Funktionen verfügbar, da sie von Function, abgeleitet sind Function, Objectin anderen Fällen jedoch nicht. Ist __proto__jedoch überall verfügbar.
Tarik
19
So __proto__ist das eigentliche Objekt, das gespeichert und als Prototyp verwendet wird, während Myconstructure.prototypees nur eine Blaupause ist, für __proto__die das tatsächlich gespeicherte und als Prototyp verwendete Objekt infakt ist. Daher myobject.prototypewäre es keine Eigenschaft des tatsächlichen Objekts, da es nur eine temporäre Sache ist, die von der Konstruktorfunktion verwendet wird, um zu skizzieren, wie myobject.__proto__sie aussehen soll.
Alex_Nabu
9
Ist es fair zu sagen, dass die __proto__Eigenschaft eines Objekts ein Zeiger auf die prototypeEigenschaft der Konstruktorfunktion des Objekts ist ? dh foo .__ proto__ === foo.constructor.prototype
Niko Bellic
10
@Alex_Nabu Nicht ganz. newCar.__proto__ IS Car.prototype , keine Instanz von Car.prototype. Während Car.protoype IS eine Instanz eines object. Car.prototypeist nicht etwas , das gibt newCarkeine Eigenschaften oder die Struktur, es ist einfach IST die nächste objectin newCar‚s - Prototyp - Kette. Car.prototypeist keine vorübergehende object. Es ist das object, was als Wert der __proto__Eigenschaft aller neuen objects festgelegt wird, die mit Carals erstellt wurden constructor. Wenn Sie irgendetwas als Vorlage denken object, denken Sie an Carals Vorlage für neue Auto- objects.
Seangwright
336

prototypeist eine Eigenschaft eines Funktionsobjekts. Es ist der Prototyp von Objekten, die von dieser Funktion erstellt wurden.

__proto__ist die interne Eigenschaft eines Objekts und zeigt auf seinen Prototyp. Aktuelle Standards bieten eine äquivalente Object.getPrototypeOf(O)Methode, obwohl der De-facto-Standard __proto__schneller ist.

Sie können instanceofBeziehungen finden, indem Sie die Funktionen einer Funktion prototypemit der __proto__Kette eines Objekts vergleichen , und Sie können diese Beziehungen durch Ändern aufheben prototype.

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var myPoint = new Point();

// the following are all true
myPoint.__proto__ == Point.prototype
myPoint.__proto__.__proto__ == Object.prototype
myPoint instanceof Point;
myPoint instanceof Object;

Hier Pointist eine Konstruktorfunktion, die prozedural ein Objekt (Datenstruktur) erstellt. myPointist ein Objekt, das von Point()so erstellt wurde Point.prototype, myPoint.__proto__dass es zu diesem Zeitpunkt gespeichert wird.

Imp
quelle
2
Wenn Sie die __proto__Eigenschaft eines Objekts ändern , ändert sich auch das Objekt, für das Prototypsuchen durchgeführt werden. Sie können beispielsweise ein Methodenobjekt als Funktion hinzufügen __proto__, um eine Art aufrufbares Instanzobjekt zu erhalten.
kzh
myPoint .__ proto __. constructor.prototype == Point.prototype
Francisco
@kzh lol das hat mir ein lustiges Ergebnis gebracht console.log(obj1.call) // [Function: call] obj1.call()// TypeError: obj1.call ist keine Funktion. Ich habeobj.__proto__ = Function.__proto__
abhisekp
myFn.__proto__ = {foo: 'bar'}
kzh
Ich glaube, ich habe deinen Standpunkt verstanden.
ComicScrip
120

Die Prototyp-Eigenschaft wird erstellt, wenn eine Funktion deklariert wird.

Zum Beispiel:

 function Person(dob){
    this.dob = dob
 }; 

Person.prototypeDie Eigenschaft wird intern erstellt, sobald Sie die obige Funktion deklariert haben. Dem Person.prototype können viele Eigenschaften hinzugefügt werden, die von Personeninstanzen gemeinsam genutzt werden, die mit new Person () erstellt wurden.

// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob}; 

Es ist erwähnenswert, dass dies standardmäßig Person.prototypeein ObjectLiteral ist (es kann nach Bedarf geändert werden).

Jede mit erstellte Instanz new Person()verfügt über eine __proto__Eigenschaft, die auf die verweist Person.prototype. Dies ist die Kette, die zum Durchlaufen verwendet wird, um eine Eigenschaft eines bestimmten Objekts zu finden.

var person1 = new Person(somedate);
var person2 = new Person(somedate);

Erstellt 2 Instanzen von Person, können diese 2 Objekte die ageMethode Person.prototypeas person1.age, person2.age.

In dem obigen Bild aus Ihrer Frage können Sie sehen, dass Fooes sich um ein handelt Function Objectund daher einen __proto__Link zu dem hat, Function.prototypeder wiederum eine Instanz von ist Objectund einen __proto__Link zu hat Object.prototype. Der Proto-Link endet hier mit __proto__dem Object.prototypeHinweis auf null.

Jedes Objekt kann auf alle Eigenschaften seiner Protokette zugreifen, die durch verknüpft sind __proto__, und bildet so die Grundlage für die prototypische Vererbung.

__proto__ist kein Standard für den Zugriff auf die Prototypenkette, sondern der Standardansatz, der jedoch ähnlich ist Object.getPrototypeOf(obj).

Der folgende Code für den instanceofBediener gibt ein besseres Verständnis:

Der instanceofOperator object class wird zurückgegeben, truewenn ein Objekt eine Instanz einer Klasse ist. Insbesondere wenn Class.prototypesich das Objekt in der Protokette dieses Objekts befindet, ist das Objekt eine Instanz dieser Klasse.

function instanceOf(Func){
  var obj = this;
  while(obj !== null){
    if(Object.getPrototypeOf(obj) === Func.prototype)
      return true;
    obj = Object.getPrototypeOf(obj);
  }
  return false;
}      

Die obige Methode kann wie instanceOf.call(object, Class)folgt aufgerufen werden: Diese gibt true zurück, wenn das Objekt eine Instanz der Klasse ist.

sid_k_reddy
quelle
2
Ich habe mich gefragt, warum das prototypeObjekt überhaupt intern erstellt wurde. Könnte man dem Funktionsobjekt selbst einfach statische Methoden zuweisen? zB function f(a){this.a = a}; f.increment = function(){return ++this.a}? Warum wurde dieser Weg nicht gewählt, anstatt die Methoden zum prototypeObjekt hinzuzufügen ? Dies funktioniert, wenn f.__proto__ = gg die Basisklasse ist.
Abhisekp
Möglicherweise wurde das prototypeObjekt für die Freigabe ausgewählt, da nur die exklusiven Eigenschaften des Funktionskonstruktors im Funktionskonstruktorobjekt gespeichert werden können.
Abhisekp
1
Tatsächlich wäre das ein Chaos, da instanceofdies dazu führen ({}) instanceof Function === truewürde, dass es keine Möglichkeit gibt, zwischen Prototypen zu unterscheiden, wenn die prototypeEigenschaft entfernt wird.
Abhisekp
@abhisekp Was meinst du damit: "Dies funktioniert, wenn f .__ proto__ = g wobei g die Basisklasse ist." Ich weiß nicht, ob dies eine Bedeutung hat, die ich nicht verstehe, aber wenn Sie die Eigenschaften und Methoden auf diese Weise hinzufügen newwürden, würden die Eigenschaften und Methoden nicht kopiert , wenn Sie das Schlüsselwort zum Erstellen einer Instanz verwenden würden Über.
DoubleOrt
67

Eine schöne Art, daran zu denken, ist ...

prototypewird von constructor()Funktionen verwendet. Es hätte eigentlich so etwas heißen sollen "prototypeToInstall", denn so ist es.

und __proto__ist dieser "installierte Prototyp" auf einem Objekt (der auf dem Objekt von dieser constructor()Funktion erstellt / installiert wurde )

Sarink
quelle
2
Ich habe es hochgestimmt, aber vielleicht war der Grund für die Abwertung, dass die Aussage "Prototyp wird von Konstruktor () -Funktionen verwendet" so klingt, als ob Nicht-Konstruktorfunktionen keine haben, was nicht der Fall ist, aber außerdem ist es jetzt auch nicht unser Fokus man kann feststellen, dass jede Funktion möglicherweise ein Konstruktor ist, wenn sie mit new ...
yoel halb
2
Bitte ändern Sie " constructor()Funktionen" in "Konstruktorfunktionen", da es zu Verwechslungen mit " __proto__.constructor()Funktionen" kommen kann. Ich halte dies für wichtig, da der Konstruktor __proto __. Nicht verwendet wird, wenn ein newSchlüsselwort verwendet wird.
Alexander Gonchiy
1
Die Aussage, dass " Prototyp von Konstruktor () -Funktionen verwendet wird ", sagt nur einen Teil einer wichtigen Tatsache aus, aber auf eine Weise, die den Leser wahrscheinlich zu der Annahme veranlasst, dass es sich um die ganze Tatsache handelt. Der Prototyp wird intern für jede Funktionsdeklaration in Javascript erstellt, unabhängig davon, wie diese Funktion in Zukunft aufgerufen wird - mit oder ohne das neue Schlüsselwort. Der Prototyp einer deklarierten Funktion zeigt auf ein Objektliteral.
Yiling
62

Zur Erklärung erstellen wir eine Funktion

 function a (name) {
  this.name = name;
 }

Wenn JavaScript diesen Code ausführt, fügt es eine prototypeEigenschaft hinzu a. prototypeEigenschaft ist ein Objekt mit zwei Eigenschaften:

  1. constructor
  2. __proto__

Also wenn wir es tun

a.prototype es kehrt zurück

     constructor: a  // function definition
    __proto__: Object

Wie Sie sehen, constructorist nichts anderes als die Funktion aselbst und __proto__zeigt auf die Stammebene Objectvon JavaScript.

Lassen Sie uns sehen, was passiert, wenn wir die aFunktion mit dem newSchlüsselwort verwenden.

var b = new a ('JavaScript');

Wenn JavaScript diesen Code ausführt, werden vier Dinge ausgeführt:

  1. Es wird ein neues Objekt erstellt, ein leeres Objekt // {}
  2. Es schafft __proto__auf bund macht es zum Punkt a.prototypesob.__proto__ === a.prototype
  3. Es a.prototype.constructorwird amit dem neu erstellten Objekt (das in Schritt 1 erstellt wurde) als Kontext (dies) ausgeführt (was eine Definition der Funktion ist ), daher wird die nameals 'JavaScript' übergebene Eigenschaft (die hinzugefügt wird this) dem neu erstellten Objekt hinzugefügt.
  4. Es gibt ein neu erstelltes Objekt in zurück (erstellt in Schritt 1), sodass var bdem neu erstellten Objekt zugewiesen wird.

Wenn wir nun hinzufügen a.prototype.car = "BMW"und tun b.car, erscheint die Ausgabe "BMW".

Dies liegt daran, dass JavaScript bei der Ausführung dieses Codes, für den es nach carEigenschaften gesucht bhat, nicht das verwendete JavaScript gefunden hat b.__proto__(das in Schritt 2 auf 'a.prototype' verweist) und die carEigenschaft gefunden hat, also "BMW" zurückgeben.

Manishz90
quelle
2
1. constructorkommt nicht zurück a()! Es kehrt zurück a. 2. gibt __proto__zurück Object.prototype, nicht das Stammobjekt in Javascript.
DoubleOrt
1
Das ist eine großartige Antwort!
John Raymon
+1 Dies ist die beste Antwort, um zu erklären, welcher Prototyp tatsächlich IST (ein Objekt mit zwei Eigenschaften) und wie Javascript jeden Code ausführt. Diese Informationen sind überraschend schwer zu bekommen.
java-addict301
53

Prototyp VS. __proto__ VS. [[Prototyp]]

Beim Erstellen einer Funktion wird automatisch ein Eigenschaftsobjekt namens Prototyp erstellt (Sie haben es nicht selbst erstellt) und an das Funktionsobjekt (the constructor) angehängt .
Hinweis : Dieses neue Prototypobjekt verweist auch auf das native JavaScript-Objekt oder hat einen intern-privaten Link zu diesem.

Beispiel:

function Foo () {
    this.name = 'John Doe';
}

// Foo has an object property called prototype.
// prototype was created automatically when we declared the function Foo.
Foo.hasOwnProperty('prototype'); // true

// Now, we can assign properties and methods to it:
Foo.prototype.myName = function () {
    return 'My name is ' + this.name;
}

Wenn Sie ein neues Objekt aus Foodem newSchlüsselwort erstellen, erstellen Sie im Grunde (unter anderem) ein neues Objekt, das einen internen oder privaten Link zum Foozuvor diskutierten Prototyp der Funktion hat :

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true


Die private Verknüpfung mit dem Objekt dieser Funktion wird als Prototyp mit doppelten Klammern oder einfach bezeichnet [[Prototype]]. Viele Browser bieten uns eine öffentliche Verknüpfung dazu an, die aufgerufen hat __proto__!

Genauer gesagt __proto__handelt es sich tatsächlich um eine Getter-Funktion , die zum nativen JavaScript-Objekt gehört. Es gibt die intern-private Prototyp-Verknüpfung der thisBindung zurück (gibt die [[Prototype]]von zurück b):

b.__proto__ === Foo.prototype // true

Es ist erwähnenswert, dass Sie ab dem Start ECMAScript5auch die Methode getPrototypeOf verwenden können, um die interne private Verknüpfung abzurufen :

Object.getPrototypeOf(b) === b.__proto__ // true


HINWEIS: diese Antwort nicht die Absicht , den gesamten Prozess der Erstellung neue Objekte oder neue Konstrukteure zu decken, aber zu helfen besser zu verstehen , was ist __proto__, prototypeund [[Prototype]]und wie es funktioniert.

Lior Elrom
quelle
2
@ Stier, klicken Sie auf die Überschrift, es führt zum ECMAScript-Spezifikationsdokument. Lesen Sie Abschnitt 9 (Verhalten bei gewöhnlichen und exotischen Objekten), in dem dies ausführlicher erläutert wird.
Lior Elrom
Ich denke, hier liegt ein Fehler vor: _ ein neues Objekt mit einer internen oder privaten Verknüpfung zum Funktionsprototyp Foo_ Meinst du: ein neues Objekt mit einer internen oder privaten Verknüpfung zum Funktionsprototyp der Funktion Foo ?
Koray Tugay
1
Danke @KorayTugay! Ja, ich habe es falsch geschrieben :) +1
Lior Elrom
31

Um es zusätzlich zu den oben genannten tollen Antworten ein wenig klarer zu machen:

function Person(name){
    this.name = name
 }; 

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

Instanzen haben __proto__ , Klassen haben Prototypen .

serkan
quelle
12

In JavaScript kann eine Funktion als Konstruktor verwendet werden. Das heißt, wir können mit dem neuen Schlüsselwort Objekte daraus erstellen. Zu jeder Konstruktorfunktion gehört ein eingebautes Objekt, das mit ihnen verkettet ist. Dieses eingebaute Objekt wird als Prototyp bezeichnet.Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

Prototyp-Diagramm

  1. Zuerst haben wir einen Konstruktor erstellt : function Foo(){}. Foo ist nur eine weitere Funktion. Wir können jedoch mit dem neuen Schlüsselwort ein Objekt daraus erstellen. Deshalb nennen wir es die Konstruktorfunktion

  2. Jede Funktion verfügt über eine eindeutige Eigenschaft, die als Prototyp-Eigenschaft bezeichnet wird. Die Konstruktorfunktion Fooverfügt also über eine Prototyp-Eigenschaft, die auf ihren Prototyp verweist Foo.prototype(siehe Abbildung).

  3. Konstruktorfunktionen sind selbst eine Funktion, die eine Instanz eines Systemkonstruktors ist, der als [[Function]] - Konstruktor bezeichnet wird. Wir können also sagen, dass dies function Foovon einem [[Function]] - Konstruktor konstruiert wird. So __proto__unseres Foo functionWillens Punkt zum Prototyp ihres Baumeisters, das ist Function.prototype.

  4. Function.prototypeis selbst ist nichts anderes als ein Objekt, das aus einem anderen Systemkonstruktor namens aufgebaut ist [[Object]]. Also, [[Object]]ist der Konstruktor von Function.prototype. Wir können also sagen, es Function.prototypehandelt sich um eine Instanz von [[Object]]. Also __proto__von Function.prototypePunkten zu Object.prototype.

  5. Object.prototypeist der letzte Mann in der Prototypenkette. Ich meine, es wurde nicht gebaut. Es ist bereits im System vorhanden. Also seine __proto__Punkte zu null.

  6. Nun kommen wir zu Instanzen von Foo. Wenn wir eine Instanz mit erstellen new Foo(), wird ein neues Objekt erstellt, das eine Instanz von ist Foo. Das heißt, es Fooist der Konstruktor dieser Instanzen. Hier haben wir zwei Instanzen erstellt (x und y). __proto__von x und y zeigt also auf Foo.prototype.

AL-Zami
quelle
Um ganz klar zu sein: Instanzen haben keine .prototype-Eigenschaft? Nur die Konstruktorfunktion richtig? ... Ein Unterschied zwischen einer Instanz und ihrer Konstruktorfunktion besteht also darin, dass Konstruktorfunktionen beide 1. proto 2. .prototype-Objekte haben, während die Instanzen nur die .__ proto__ -Eigenschaft haben ... richtig?
Shaz
@Shaz du hast recht. Instanzen verwenden ihr Proto, um auf die Prototyp-Eigenschaft ihrer Konstruktorfunktion zuzugreifen.
AL-Zami
Aber warum, warum, wenn Sie schreiben: var car = Object.create (Vehicle); Sie erhalten Auto .__ proto__ = Fahrzeug ABER Sie erhalten auch eine Eigenschaft car.prototype, die auf Vehicle.prototype verweist?
Shaz
@shaz kannst du eine jsfiddle bereitstellen, damit ich die situation visualisieren kann?
AL-Zami
1
hier ist car.prototype eine geerbte Eigenschaft. Das Auto erbt die Eigenschaft "Prototyp" von der Fahrzeugfunktion. also auto.prototyp === fahrzeug.prototyp. "Prototyp" -Eigenschaft ist eine Eigenschaft am Fahrzeug. Das Auto kann über seine Prototypenkette darauf zugreifen. Ich hoffe, dies wird Ihre Verwirrung
beseitigen
8

Zusammenfassung:

Die __proto__Eigenschaft eines Objekts ist eine Eigenschaft, die prototypeder Konstruktorfunktion des Objekts zugeordnet ist. Mit anderen Worten:

instance.__proto__ === constructor.prototype // true

Dies wird verwendet, um die prototypeKette eines Objekts zu bilden. Die prototypeKette ist ein Suchmechanismus für Eigenschaften eines Objekts. Wenn auf die Eigenschaft eines Objekts zugegriffen wird, überprüft JavaScript zuerst das Objekt selbst. Wenn das Grundstück dort nicht gefunden wird, steigt es bis zum anprotochain ihrer Entdeckung (oder auch nicht).

Beispiel:

function Person (name, city) {
  this.name = name;
}

Person.prototype.age = 25;

const willem = new Person('Willem');

console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor

console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype
console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function 

Unser erstes Protokoll führt zu true, weil, wie erwähnt, die __proto__Eigenschaft der vom Konstruktor erstellten Instanz auf die verweistprototype Eigenschaft des . Denken Sie daran, dass Funktionen in JavaScript auch Objekte sind. Objekte können Eigenschaften haben, und eine Standardeigenschaft jeder Funktion ist eine Eigenschaft namens Prototyp.

Wenn diese Funktion dann als Konstruktorfunktion verwendet wird, erhält das von ihr instanziierte Objekt eine aufgerufene Eigenschaft __proto__. Und diese __proto__Eigenschaft bezieht sich auf die prototypeEigenschaft der Konstruktorfunktion (die standardmäßig jede Funktion hat).

Warum ist das nützlich?

JavaScript verfügt über einen Mechanismus zum Nachschlagen von Eigenschaften, Objectsder als "prototypische Vererbung" bezeichnet wird. Im Folgenden wird Folgendes ausgeführt:

  • Zunächst wird überprüft, ob sich die Eigenschaft auf dem Objekt selbst befindet. In diesem Fall wird diese Eigenschaft zurückgegeben.
  • Befindet sich die Eigenschaft nicht auf dem Objekt selbst, klettert sie die Protochain hinauf. Grundsätzlich wird das Objekt betrachtet, auf das sich die __proto__Eigenschaft bezieht . Dort wird geprüft, ob die Eigenschaft für das Objekt verfügbar ist, auf das von verwiesen wird __proto__.
  • Wenn sich die Eigenschaft nicht auf dem __proto__Objekt befindet, klettert sie die __proto__Kette hinauf bis zum ObjectObjekt.
  • Wenn die Eigenschaft an keiner Stelle des Objekts und seiner prototypeKette gefunden werden kann, wird sie zurückgegeben undefined.

Zum Beispiel:

function Person (name) {
  this.name = name;
}

let mySelf = new Person('Willem');

console.log(mySelf.__proto__ === Person.prototype);

console.log(mySelf.__proto__.__proto__ === Object.prototype);

Willem van der Veen
quelle
7

Ich lerne zufällig Prototypen von You Don't Know JS: this & Object Prototypes , ein wunderbares Buch, um das darunter liegende Design zu verstehen und so viele Missverständnisse zu klären (deshalb versuche ich, Vererbung und ähnliches zu vermeiden instanceof).

Aber ich habe die gleiche Frage wie die Leute, die hier gestellt wurden. Einige Antworten sind wirklich hilfreich und aufschlussreich. Ich würde auch gerne mein Verständnis teilen.


Was ist ein Prototyp?

Objekte in JavaScript haben eine interne Eigenschaft, die in der Spezifikation als [[Prototype]]bezeichnet wird und lediglich auf ein anderes Objekt verweist. Fast alle Objekte erhalten eine Nicht-null zum Zeitpunkt ihrer Erstellung für diese Eigenschaft.

Wie bekomme ich den Prototyp eines Objekts?

über __proto__oderObject.getPrototypeOf

var a = { name: "wendi" };
a.__proto__ === Object.prototype // true
Object.getPrototypeOf(a) === Object.prototype // true

function Foo() {};
var b = new Foo();
b.__proto__ === Foo.prototype
b.__proto__.__proto__ === Object.prototype

Was ist das prototype?

prototypeist ein Objekt, das automatisch als spezielle Eigenschaft einer Funktion erstellt wird und zum Einrichten der Delegierungskette (Vererbungskette), auch als Prototypkette bezeichnet, verwendet wird.

Wenn wir eine Funktion erstellen a, prototypewird automatisch als besondere Eigenschaft erstellt auf aund speichert den Funktionscode auf als constructorauf prototype.

function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true

Ich würde diese Eigenschaft gerne als Speicherort für die Eigenschaften (einschließlich Methoden) eines Funktionsobjekts betrachten. Dies ist auch der Grund, warum Dienstprogrammfunktionen in JS wie folgt definiert Array.prototype.forEach()werden Function.prototype.bind():Object.prototype.toString().

Warum die Eigenschaft einer Funktion hervorheben ?

{}.prototype // undefined;
(function(){}).prototype // Object {constructor: function}

// The example above shows object does not have the prototype property.
// But we have Object.prototype, which implies an interesting fact that
typeof Object === "function"
var obj = new Object();

Also Arary, Function, Objectsind alle Funktionen. Ich sollte zugeben, dass dies meinen Eindruck auf JS auffrischt. Ich weiß, dass Funktionen in JS erstklassige Bürger sind, aber es scheint, dass sie auf Funktionen basieren.

Was ist der Unterschied zwischen __proto__und prototype?

__proto__Eine Referenz bearbeitet jedes Objekt , um auf seine [[Prototype]]Eigenschaft zu verweisen .

prototypeist ein Objekt, das automatisch als spezielle Eigenschaft einer Funktion erstellt wird wird und zum Speichern der Eigenschaften (einschließlich Methoden) eines Funktionsobjekts verwendet wird.

Mit diesen beiden konnten wir die Prototypenkette mental abbilden. Wie dieses Bild zeigt:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
ifyouseewendy
quelle
7

 JavaScript-Prototyp vs __prototype__

'use strict'
function A() {}
var a = new A();
class B extends A {}
var b = new B();
console.log('====='); // =====
console.log(B.__proto__ === A); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(b.__proto__ === B.prototype); // true
console.log(a.__proto__ === A.prototype); // true
console.log(A.__proto__ === Function.__proto__); // true
console.log(Object.__proto__ === Function.__proto__); // true
console.log(Object.prototype === Function.__proto__.__proto__); // true
console.log(Object.prototype.__proto__ === null); // true

In JavaScript hat jedes Objekt (Funktion ist auch Objekt!) Eine __proto__Eigenschaft, die Eigenschaft verweist auf seinen Prototyp.

Wenn wir den newOperator mit einem Konstruktor verwenden, um ein neues Objekt zu erstellen, wird die __proto__Eigenschaft des neuen Objekts mit der des Konstruktors festgelegtprototype Eigenschaft des Konstruktors festgelegt, und der Konstruktor wird vom neuen Objekt aufgerufen. In diesem Prozess ist "this" eine Referenz auf das neue Objekt Geben Sie im Konstruktorbereich schließlich das neue Objekt zurück.

Der Prototyp des Konstruktors ist eine __proto__Eigenschaft, die prototypeEigenschaft eines Konstruktors ist die Arbeit mit dem newOperator.

Der Konstruktor muss eine Funktion sein, aber die Funktion ist nicht immer ein Konstruktor, selbst wenn sie eine prototypeEigenschaft hat.

Die Prototypkette ist tatsächlich die __proto__Eigenschaft des Objekts, auf seinen Prototyp zu verweisen, und die __proto__Eigenschaft des Prototyps, auf den Prototyp des Prototyps zu verweisen, und so weiter, bis auf die Eigenschaft des Objektprototyps __proto__verwiesen wird, die auf null verweist.

Zum Beispiel:

console.log(a.constructor === A); // true
// "a" don't have constructor,
// so it reference to A.prototype by its ``__proto__`` property,
// and found constructor is reference to A

[[Prototype]]und __proto__Eigentum ist eigentlich dasselbe.

Wir können die getPrototypeOf-Methode von Object verwenden, um den Prototyp eines Objekts abzurufen.

console.log(Object.getPrototypeOf(a) === a.__proto__); // true

Jede von uns geschriebene Funktion kann verwendet werden, um mit dem newOperator ein Objekt zu erstellen , sodass jede dieser Funktionen ein Konstruktor sein kann.

林奕 忠
quelle
6

Ein weiterer guter Weg, um es zu verstehen:

var foo = {}

/* 
foo.constructor is Object, so foo.constructor.prototype is actually 
Object.prototype; Object.prototype in return is what foo.__proto__ links to. 
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);

Erst nachdem IE11 __proto__unterstützt wird. Vor dieser Version, wie z. B. IE9, konnten Sie die verwenden constructor, um die zu erhalten __proto__.

Yad Smood
quelle
Nur, dass ich es umgekehrt schreiben würde: foo .__ proto__ === foo.constructor.prototype
epeleg
6

Prototyp

Prototyp ist eine Eigenschaft einer Funktion. Dies ist die Blaupause zum Erstellen von Objekten mithilfe dieser (Konstruktor-) Funktion mit einem neuen Schlüsselwort.

__proto__wird in der Suchkette verwendet, um Methoden und Eigenschaften aufzulösen. Wenn ein Objekt erstellt wird (unter Verwendung der Konstruktorfunktion mit neuem Schlüsselwort), __proto__wird es auf (Konstruktor) Function.prototype gesetzt

function Robot(name) {
    this.name = name;
}
var robot = new Robot();

// the following are true   
robot.__proto__ == Robot.prototype
robot.__proto__.__proto__ == Object.prototype

Hier ist meine (imaginäre) Erklärung, um die Verwirrung zu beseitigen:

Stellen Sie sich vor, es gibt eine imaginäre Klasse (Blueprint / Coockie Cutter), die der Funktion zugeordnet ist. Diese imaginäre Klasse wird verwendet, um Objekte zu instanziieren. prototypeist der Erweiterungsmechanismus (Erweiterungsmethode in C # oder Swift Extension), um dieser imaginären Klasse Dinge hinzuzufügen.

function Robot(name) {
    this.name = name;
}

Das Obige kann man sich vorstellen als:

// imaginary class
class Robot extends Object{

    static prototype = Robot.class  
    // Robot.prototype is the way to add things to Robot class
    // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype

    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

} 

Damit,

var robot = new Robot();

robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype

Fügen Sie nun eine Methode zum prototypeof Robot hinzu:

Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y};
// Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)

Das Obige kann als Erweiterung der Roboterklasse vorgestellt werden:

// Swift way of extention
extension Robot{
    function move(x, y){    
        Robot.position.x = x; Robot.position.y = y
    }
}

Was wiederum,

// imaginary class
class Robot{

    static prototype = Robot.class // Robot.prototype way to extend Robot class
    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

    // added by prototype (as like C# extension method)
    function move(x, y){ 
        Robot.position.x = x; Robot.position.y = y
    };
}
Hassan Tareq
quelle
Ich denke immer noch an kohärentere Namen __proto__und Prototypen. vielleicht Prototyp und Vererbung?
Dmitry
Ich würde sagen, prototypeund __proto__beides sollte vermieden werden. Wir haben jetzt Unterricht und ich mag OOP.
Hassan Tareq
Das Problem ist, dass die Klasse relativ neu ist und nicht von wirklich praktischen Engines wie Microsoft JScript (schön zu haben, wenn Sie an C arbeiten und eine schnelle und schmutzige Skript-Engine benötigen, die immer da ist) und Nashorn-Javascript (das mit allem geliefert wird) unterstützt wird neue Java-Installationen unter jjs und ist eine gute Möglichkeit, Java in eine rein dynamische Umgebung zu bringen, in der Sie nicht ständig neu kompilieren müssen. Die Sache ist, wenn Klasse Zucker wäre, wäre es kein Problem, aber es ist nicht so, es bietet Dinge, die ohne sie in älteren js-Versionen unmöglich sind. Wie die Erweiterung von "Funktion".
Dmitry
Irgendwann werden wir Unterstützung bekommen. Ich bin Backend-Entwickler, habe also keine Probleme, ich codiere selten in js.
Hassan Tareq
und statische Elemente so zu erben, dass das Hinzufügen neuer / das Entfernen statischer Elemente vom übergeordneten Element vom Kind bemerkt wird (was ich mir bei JScript nicht vorstellen kann, das Object.assign / __ proto __ / getPrototypeOf nicht bietet, also Sie muss mit dem root Object.prototype basteln, um es zu simulieren)
Dmitry
4

Einfach gesagt:

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

Auf diese Weise können Sie Eigenschaften an X.prototype anhängen, nachdem Objekte vom Typ X instanziiert wurden, und sie erhalten weiterhin Zugriff auf diese neuen Eigenschaften über die __proto__- Referenz, mit der die Javascript-Engine die Prototypenkette durchläuft.

Andreas Bergström
quelle
4

Prototype oder Object.prototype ist eine Eigenschaft eines Objektliteral. Es stellt das Objekt Prototyp - Objekt , das Sie überschreiben können mehr Eigenschaften oder Methoden weiter entlang der Prototypkette hinzuzufügen.

__proto__ ist eine Accessor-Eigenschaft (Funktion zum Abrufen und Festlegen ), die den internen Prototyp eines Objekts verfügbar macht, über das zugegriffen wird.

Verweise:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
  2. http://www.w3schools.com/js/js_object_prototypes.asp

  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

akodevs
quelle
Object.prototypeist keine Eigenschaft eines Objektliteral, beim Versuch, {}.prototypeRückgaben undefiniert auszudrucken ; Es kann jedoch über zugegriffen werden {}.__proto__, was zurückkehrt Object.prototype.
DoubleOrt
3

Ich weiß, ich bin spät dran, aber lassen Sie mich versuchen, es zu vereinfachen.

Nehmen wir an, es gibt eine Funktion

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

Bei der Foo-Funktion wird ein Prototypobjekt verknüpft. Wenn wir also eine Funktion in JavaScript erstellen, ist immer ein Prototypobjekt damit verknüpft.

Lassen Sie uns nun zwei Objekte mit der Funktion Foo erstellen.

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);
  1. Jetzt haben wir zwei Objekte, Objekt a und Objekt b. Beide werden mit dem Konstruktor Foo erstellt. Denken Sie daran, Konstruktor ist hier nur ein Wort.
  2. Objekt a und b haben beide eine Kopie der Nachrichteneigenschaft.
  3. Diese beiden Objekte a und b sind mit dem Prototypobjekt des Konstruktors Foo verknüpft.
  4. Auf den Objekten a und b können wir in allen Browsern mit der Eigenschaft proto auf den Foo-Prototyp zugreifen, und im IE können wir Object.getPrototypeOf (a) oder Object.getPrototypeOf (b) verwenden.

Nun, Foo.prototype, a. Proto und b. proto all bezeichnet dasselbe Objekt.

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;

alles oben Genannte würde wahr zurückgeben.

Wie wir wissen, können in JavaScript Eigenschaften dynamisch hinzugefügt werden. Wir können dem Objekt eine Eigenschaft hinzufügen

    Foo.prototype.Greet = function(){

         console.log(this.message);
    }
    a.Greet();//a
    b.Greet();//b
    a.constructor.prototype.Greet();//undefined 

Wie Sie sehen, haben wir in Foo.prototype die Greet () -Methode hinzugefügt, auf die jedoch in a und b oder in jedem anderen Objekt zugegriffen werden kann, das mit Foo erstellt wurde.

Während der Ausführung von a.Greet () durchsucht JavaScript zuerst Greet in Objekt a in der Eigenschaftsliste. Wenn es nicht gefunden wird, wird es in der Protokette von a hochgehen . Seit einem. proto und Foo.prototype sind dasselbe Objekt, JavaScript findet die Greet () -Methode und führt sie aus.

Ich hoffe, jetzt sind Prototyp und Proto etwas vereinfacht.

Debug-Modus
quelle
3

Erklärendes Beispiel:

function Dog(){}
Dog.prototype.bark = "woof"

let myPuppie = new Dog()

Jetzt hat myPupppie eine __proto__Eigenschaft, die auf Dog.prototype verweist.

> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}

myPuppie hat jedoch KEINE Prototyp-Eigenschaft.

> myPuppie.prototype
>> undefined

Also, __proto__von mypuppie ist der Verweis auf die .prototype Eigenschaft der Konstruktor - Funktion , die verwendet wurde , um dieses Objekt zu instanziieren (und das aktuelle myPuppie Objekt „Delegierten“ Beziehung zu diesem __proto__Objekt), während .prototype Eigenschaft myPuppie einfach nicht vorhanden ist (da wir haben es nicht eingestellt).

Gute Erklärung von MPJ hier: Proto vs Prototyp - Objekterstellung in JavaScript

Nitin Jadhav
quelle
3

Ich habe für mich eine kleine Zeichnung erstellt, die den folgenden Codeausschnitt darstellt:

var Cat = function() {}
var tom = new Cat()

__Proto__ und Prototyp verstehen

Ich habe einen klassischen OO-Hintergrund, daher war es hilfreich, die Hierarchie auf diese Weise darzustellen. Behandeln Sie die Rechtecke im Bild als JavaScript-Objekte, damit Sie dieses Diagramm besser lesen können. Und ja, Funktionen sind auch Objekte. ;)

Objekte in JavaScript haben Eigenschaften und __proto__sind nur eine davon.

Die Idee hinter dieser Eigenschaft ist, auf das Vorfahrenobjekt in der (Vererbungs-) Hierarchie zu verweisen.

Das Stammobjekt in JavaScript ist Object.prototypeund alle anderen Objekte sind Nachkommen dieses Objekts . Die __proto__Eigenschaft des Stammobjekts ist null, das das Ende der Vererbungskette darstellt.

Sie werden feststellen, dass dies prototypeeine Eigenschaft von Funktionen ist. Catist eine Funktion, aber auch Functionund Objectsind (native) Funktionen. tomist keine Funktion, hat also diese Eigenschaft nicht.

Die Idee hinter dieser Eigenschaft ist, auf ein Objekt zu verweisen, das in der Konstruktion verwendet wird, dh wenn Sie den newOperator für diese Funktion aufrufen .

Beachten Sie, dass Prototypobjekte (gelbe Rechtecke) eine andere Eigenschaft haben, constructordie auf das jeweilige Funktionsobjekt verweist. Aus Gründen der Kürze wurde dies nicht dargestellt.

Wenn wir das tomObjekt mit erstellen new Cat(), wird für das erstellte Objekt die __proto__Eigenschaft auf das prototypeObjekt der Konstruktorfunktion festgelegt.

Lassen Sie uns am Ende ein wenig mit diesem Diagramm spielen. Die folgenden Aussagen sind wahr:

  • tom.__proto__Eigenschaft zeigt auf dasselbe Objekt wie Cat.prototype.

  • Cat.__proto__zeigt auf das Function.prototypeObjekt, genau wie Function.__proto__und Object.__proto__tun.

  • Cat.prototype.__proto__und tom.__proto__.__proto__auf das gleiche Objekt zeigen und das ist Object.prototype.

Prost!

das Licht
quelle
Sehr gut erklärt!
StackOverflow UI
@theshinylight, tom.__proto__und Cat.prototypesind streng gleich, also, tom.__proto__ === Cat.prototype und Cat.prototype === tom.__proto__sind wahr. Also, was hast du mit dem Pfeil im Bild gemeint?
aXuser264
Der schwarze Pfeil (wenn Sie sich darauf beziehen) hat keine andere Bedeutung als die Eigenschaft des Objekts. So prototypeist das Eigentum des CatObjekts (aus Ihrer Frage).
Licht
2

DEFINITIONEN

(Die Zahl in Klammern () ist ein 'Link' zu dem unten angegebenen Code.)

prototype- ein Objekt, das besteht aus:
=> Funktionen (3) dieses bestimmten ConstructorFunction.prototype(5), auf die jedes Objekt (4) zugreifen kann, das über diese Konstruktorfunktion (1) erstellt wurde oder erstellt werden soll (1)
=> der Konstruktorfunktion selbst (1) )
=> __proto__dieses bestimmten Objekts (Prototypobjekt)

__proto__(dandor proto?) - eine Verknüpfung zwischen einem Objekt (2), das durch eine bestimmte Konstruktorfunktion (1) erstellt wurde, UND den Eigenschaften des Prototypobjekts (5) dieses Konstruktors, die jedem erstellten Objekt (2) den Zugriff auf die Funktionen des Prototyps ermöglichen und Methoden (4) ( __proto__ist standardmäßig in jedem einzelnen Objekt in JS enthalten)

CODE-ERKLÄRUNG

1.

    function Person (name, age) {
        this.name = name;
        this.age = age;} 

2.

    var John = new Person(‘John’, 37);
    // John is an object

3.

    Person.prototype.getOlder = function() {
        this.age++;
    }
    // getOlder is a key that has a value of the function

4.

    John.getOlder();

5.

    Person.prototype;
Eduard
quelle
1

Ich werde eine Erklärung für die 4. Klasse versuchen:

Die Dinge sind sehr einfach. A prototypeist ein Beispiel dafür, wie etwas gebaut werden sollte. Damit:

  • Ich bin ein functionund baue neue Objekte ähnlich meinenprototype

  • Ich bin ein objectund ich wurde mit meinem __proto__als Beispiel gebaut

Beweis :

function Foo() { }

var bar = new Foo()

// `bar` is constructed from how Foo knows to construct objects
bar.__proto__ === Foo.prototype // => true

// bar is an instance - it does not know how to create objects
bar.prototype // => undefined
vladCovaliov
quelle
1
Nein, weder prototypenoch a __proto__werden zu irgendeinem Zeitpunkt als Blaupause oder so verwendet, um ein Objekt zu erstellen. Dies ist ein Mythos, der durch die verschwommene classSyntax und ihre Vorgänger eingeführt wurde. Wie der Antwort-Post sagt, wird er nur für die Suchkette und für den Fall der prototypeIdentifizierung constructorverwendet new(was Teil dieses Mechanismus ist, der vorgibt, klassisch zu sein, der viele Benutzer, einschließlich mich, verwirrt).
Christof Kälin
Der erste Punkt sollte lauten: "Ich bin eine Funktion und baue neue Objekte, die an meinen Prototyp delegiert werden"
Nitin Jadhav,
1

Jede von Ihnen erstellte Funktion hat eine Eigenschaft namens prototypeund beginnt ihr Leben als leeres Objekt. Diese Eigenschaft ist erst dann von Nutzen, wenn Sie diese Funktion als Konstruktorfunktion verwenden, dh mit dem Schlüsselwort 'new'.

Dies wird oft mit der __proto__Eigenschaft eines Objekts verwechselt . Einige könnten verwirrt werden und außer dass die prototypeEigenschaft eines Objekts sie zum Proto eines Objekts machen könnte. Dies ist jedoch nicht der Fall. prototypewird verwendet, um das __proto__eines Objekts abzurufen, das aus einem Funktionskonstruktor erstellt wurde.

Im obigen Beispiel:

function Person(name){
    this.name = name
}; 

var eve = new Person("Eve");

console.log(eve.__proto__ == Person.prototype) // true
// this is exactly what prototype does, made Person.prototype equal to eve.__proto__

Ich hoffe es macht Sinn.

Malkeet Singh
quelle
1
prototypewird nicht zum Erstellen __proto__eines Objekts verwendet. __proto__liefert beim Zugriff lediglich einen Verweis auf das prototypeObjekt.
DoubleOrt
1

Was ist mit __proto__statischen Methoden?

function Foo(name){
  this.name = name
  Foo.__proto__.collection.push(this)
  Foo.__proto__.count++

}

Foo.__proto__.count=0
Foo.__proto__.collection=[]

var bar = new Foo('bar')
var baz = new Foo('baz')

Foo.count;//2
Foo.collection // [{...}, {...}]
bar.count // undefined
Barrard
quelle
Genau deshalb eine Antwort auf " __proto__VS. prototypein JavaScript" ?
Andreas
ist es gut oder was ist mit Foo.collection.push (this) Foo.count ++
Selva Ganapathi
1

(function(){ 
      let a = function(){console.log(this.b)};
      a.prototype.b = 1;
      a.__proto__.b = 2;
      let q = new a();
      console.log(a.b);
      console.log(q.b) 
    })()

Versuchen Sie diesen Code zu verstehen

Timur
quelle
1

Es gibt nur ein Objekt, das für die protypische Verkettung verwendet wird. Dieses Objekt hat offensichtlich einen Namen und einen Wert: __proto__ist sein Name und prototypeist sein Wert. Das ist alles.

Um es noch einfacher zu verstehen, schauen Sie sich das Diagramm oben in diesem Beitrag an (Diagramm von dmitry soshnikov). Sie werden niemals __proto__Punkte auf etwas anderes als findenprototype als seinen Wert finden.

Das Wesentliche ist: Ist __proto__der Name, der auf das prototypische Objekt verweist, und prototypeist das eigentliche prototypische Objekt.

Es ist wie zu sagen:

let x = {name: 'john'};

xist der Objektname (Zeiger) und {name: 'john'}ist das tatsächliche Objekt (Datenwert).

HINWEIS: Dies ist nur ein massiv vereinfachter Hinweis darauf, wie sie auf hoher Ebene zusammenhängen.

Update: Hier ist ein einfaches konkretes Javascript-Beispiel zur besseren Veranschaulichung:

let x = new String("testing") // Or any other javascript object you want to create

Object.getPrototypeOf(x) === x.__proto__; // true

Dies bedeutet, dass wenn Object.getPrototypeOf(x)wir den tatsächlichen Wert von x(der sein Prototyp ist) erhalten, genau das ist, worauf der __proto__von xzeigt. Daher __proto__weist in der Tat auf den Prototyp von x. Somit __proto__verweist x(Zeiger von x) und prototypeist der Wert vonx (seinem Prototyp).

Ich hoffe es ist jetzt ein bisschen klar.

Fouad Boukredine
quelle
1

Dies ist eine sehr wichtige Frage, die für jeden relevant ist, der die prototypische Vererbung verstehen möchte. Soweit ich weiß, wird der Prototyp standardmäßig zugewiesen, wenn ein Objekt mit new aus einer Funktion erstellt wird, da Function per Definition ein Prototypobjekt hat:

function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]

Wenn wir ein gewöhnliches Objekt ohne neues erstellen, dh explizit aus einer Funktion, hat es keinen Prototyp, aber es hat ein leeres Proto , dem ein Prototyp zugewiesen werden kann.

var foo={
  check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); //  TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo

Wir können Object.create verwenden, um ein Objekt explizit zu verknüpfen.

// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`
Tksilicium
quelle
0

__proto__ist die zu konstruierende Basis prototypeund eine Konstruktorfunktion, zB: function human(){}has, prototypedie über __proto__in der neuen Instanz der Konstruktorfunktion geteilt wird. Eine ausführlichere Lektüre finden Sie hier

Jyoti Duhan
quelle
@Derick Daniel: Ich bin mir nicht sicher, warum du das abgelehnt hast, aber die Bearbeitung, die du vorgenommen hast, war nicht die, die ich vermitteln wollte. Für mehr Freigabe weiter bearbeitet :).
Jyoti Duhan
Jyoti, ich habe deine Antwort nicht abgelehnt, jemand anderes hat sie nur bearbeitet :)
Freiberufler
0

Wie dies zu Recht festgestellt wurde

__proto__ist das eigentliche Objekt, das in der Suchkette zum Auflösen von Methoden usw. verwendet wird. Der Prototyp ist das Objekt, das zum Erstellen verwendet wird, __proto__wenn Sie ein Objekt mit new erstellen:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;

Wir können ferner feststellen, dass die __proto__Eigenschaft eines Objekts, das mit dem Funktionskonstruktor erstellt wurde, auf den Speicherort zeigt, auf den der Prototyp zeigt des jeweiligen Konstruktors zeigt.

Wenn wir den Speicherort des Prototyps der Konstruktorfunktion ändern, zeigt das __proto__abgeleitete Objekt weiterhin auf den ursprünglichen Adressraum. Um gemeinsame Eigenschaften in der Vererbungskette verfügbar zu machen, hängen Sie daher die Eigenschaft immer an den Prototyp der Konstruktorfunktion an , anstatt sie neu zu initialisieren (wodurch sich ihre Speicheradresse ändern würde).

Betrachten Sie das folgende Beispiel:

function Human(){
    this.speed = 25;
}

var himansh = new Human();

Human.prototype.showSpeed = function(){
    return this.speed;
}

himansh.__proto__ === Human.prototype;  //true
himansh.showSpeed();    //25

//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}

//himansh.__proto__ will still continue to point towards the same original memory location. 

himansh.__proto__ === Human.prototype;  //false
himansh.showSpeed();    //25
Himansh
quelle
-1

Mein Verständnis ist: __proto__ und Prototyp werden alle für die Prototypenkettentechnik bereitgestellt. Der Unterschied besteht darin, dass Funktionen mit Unterstrich (wie __proto__) nicht für Entwickler gedacht sind, die explizit aufgerufen werden. Mit anderen Worten, sie sind nur für einige Mechanismen wie Erben usw. gedacht. Sie sind "Back-End". Funktionen ohne Unterstrich sind jedoch für den expliziten Aufruf vorgesehen. Sie sind "Front-End".

Beicai
quelle
3
Es gibt mehr zu __proto__und prototypeals nur die Namenskonvention. Sie können auf dasselbe Objekt zeigen oder nicht. Siehe @ Zyklus Antwort.
Demisx
1
@demisx natürlich hast du gesagt, ist richtig, aber meiner Meinung nach ist der Namensunterschied der Kontrast der Funktionalität ausgesetzt.
Beicai
Es reicht nicht aus, "nach Ihrem Verständnis" zu
sagen
-3

!!! DAS IST DIE BESTE ERKLÄRUNG DER WELT !!!!!

var q = {}
var prototype = {prop: 11}

q.prop // undefined
q.__proto__ = prototype
q.prop // 11

In Funktionskonstruktoren ruft die Javascript-Engine dies q.__proto__ = prototypeautomatisch auf, wenn wir schreiben new Class, und in das __proto__RequisitensetClass.prototype

function Class(){}
Class.prototype = {prop: 999} // set prototype as we need, before call new

var q = new Class() // q.__proto__ = Class.prototype
q.prop // 999

Genießen %)

Maxmaxmaximus
quelle