Javascript: prototype gegen __proto__

Immer wieder bin ich über zwei Javascript-Propertys gestolpert, die ich nicht wirklich zu unterscheiden wusste: Sowohl mit prototype wie auch mit __proto__ kann man auf den Prototype eines JS-Objekts zugreifen und diesen beispielsweise erweitern.

Prototypen in Javascript

Prototypen dienen in Javascript dazu, eine Art der Vererbung zu realisieren, die es aufgrund der nicht vorhandenen Klassen nicht direkt gibt. Objekte in Javascript haben einen Prototypen, diese wiederum können ebenfalls einen haben. Erzeugt man etwa ein leeres Objekt, hat dieses von Haus aus einige Eigenschaften:

var a = {};
console.log(a.toString()); // "[object Object]"

Da der Interpreter die Eigenschaft toString nicht in a finden kann, prüft er, ob er sie in dessen Prototypen findet (und ggf. in dessen Prototypen usw.). Der Prototyp von a ist (wenn nicht anders angegeben) ganz automatisch Object, welches die Methode toString bereitstellt.

Die Eigenschaft __proto__

Zwar ist dies kein ECMA-Standard, aber zumindest Chrome und Firefox vergeben jedem Objekt eine Eigenschaft __proto__, über welche man auf den Prototypen einer Objektinstanz zugreifen kann:

var a = {};
console.log(a.__proto__.constructor.name); // "Object"

Und prototype?

ECMA-Standard und viel verbreiteter ist aber die Eigenschaft prototype. Anders als __proto__ wird sie aber nicht für Objekte mitgeliefert, sondern für Funktionen:

// Kein prototype in leeren Objekt:
console.log(typeof ({}).prototype); // "undefined"
// Dafür in einer Funktion:
console.log(typeof (function(){}).prototype); // "object"

Nutzt man eine Funktion als Konstruktor, so ist der Prototyp des zurückgelieferten Objektes automatisch eine Referenz auf die Prototype-Eigenschaft der Funktion:

// Ein einfacher Konstruktor
function Person(name) {
    this.name = name;
}
// prototype der Funktion erweitern...
Person.prototype.greet = function() {
    console.log("Hello, my name is " 
                + this.name);
};

var peter = new Person("Peter");
// Prototyp ist prototype des Konstruktors:
peter.greet(); // "Hello, my name is Peter"

Kurz weitergeführt, zeigt das Beispiel noch mal den Unterschied zwischen __proto__ und prototype:

var paul = new Person("Paul");
paul.greet(); // "Hello, my name is Paul"

// paul ist Objekt, keine Funktion, hat 
// daher keine Eigenschaft prototype:
paul.prototype.greet = function() {
    console.log("Guten Tag, mein Name ist " 
                + this.name);
}; // Uncaught TypeError: 
   //   Cannot set property 'greet' of undefined

// Dafür aber die Eigenschaft __proto__
paul.__proto__.greet = function() {
    console.log("Guten Tag, mein Name ist " 
                + this.name);
};

paul.greet(); // "Guten Tag, mein Name ist Paul"

9 Kommentare

  1. Vielleicht noch zur Ergänzung / Verdeutlichung:
    paul.__proto__
    ist eine abkürzende Schreibweise für
    paul.constructor.prototype

  2. Guter Hinweis, auch wenn „abkürzende Schreibweise“ etwas unglücklich formuliert ist: Initial zeigen beide auf das selbe Objekt. Das kann man/sich aber jederzeit ändern.

  3. Sorry – wenn ich dumm frage, aber schonmal Object.definePropertie oder Object.defineProperties benutzt ?
    Diese zwei Methoden sind der Grund warum ECMA kein __proto__ im Standart benötigt – lol
    und desweiteren erlaubt uns Javascript einfach neue Props an Objekte dran zu hängen. geht alles von alleine wie von Zauberhand 🙂
    viel Spass noch beim kompliziert sein 🙂

  4. Ich weiß jetzt nicht ob das ein Witz sein soll oder ich nicht verstehe was du meinst. Dieser Artikel behandelt Javascripts Prototyping, ich sehe nicht was Object.defineProperty damit zu tun haben sollte. Dass man Objekte ändern kann sollte klar sein, wird im Artikel mehr als einmal gemacht.

Kommentare sind geschlossen.