EDIT Feb. 2012: Die Antwort unten ist nicht mehr korrekt. __proto__ wird zu ECMAScript 6 als "normativ optional" hinzugefügt, was bedeutet, dass es nicht implementiert werden muss, aber wenn dies der Fall ist, muss es den vorgegebenen Regeln folgen. Dies ist derzeit ungelöst, wird aber zumindest offiziell Teil der JavaScript-Spezifikation sein.
Diese Frage ist viel komplizierter, als es auf den ersten Blick scheint, und übersteigt die Gehaltsstufe der meisten Menschen in Bezug auf das Wissen über Javascript-Interna.
Die prototype
Eigenschaft eines Objekts wird verwendet, wenn neue untergeordnete Objekte dieses Objekts erstellt werden. Das Ändern spiegelt sich nicht im Objekt selbst wider, sondern wird reflektiert, wenn dieses Objekt als Konstruktor für andere Objekte verwendet wird, und hat keinen Sinn beim Ändern des Prototyps eines vorhandenen Objekts.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Objekte haben eine interne Eigenschaft, die auf den aktuellen Prototyp verweist. Wenn eine Eigenschaft für ein Objekt aufgerufen wird, beginnt sie am Objekt und durchläuft dann die [[Prototyp]] - Kette, bis sie nach dem Stammobjekt-Prototyp eine Übereinstimmung findet oder fehlschlägt. Auf diese Weise ermöglicht Javascript das Erstellen und Ändern von Objekten zur Laufzeit. Es hat einen Plan für die Suche nach dem, was es braucht.
Die __proto__
Eigenschaft ist in einigen Implementierungen vorhanden (viel jetzt): in jeder Mozilla-Implementierung, in allen mir bekannten Webkit-Implementierungen und in einigen anderen. Diese Eigenschaft verweist auf die interne Eigenschaft [[Prototyp]] und ermöglicht Änderungen nach der Erstellung von Objekten. Alle Eigenschaften und Funktionen werden aufgrund dieser verketteten Suche sofort auf den Prototyp umgeschaltet.
Diese Funktion ist zwar jetzt standardisiert, aber immer noch kein erforderlicher Bestandteil von JavaScript. In unterstützenden Sprachen besteht eine hohe Wahrscheinlichkeit, dass Ihr Code in die Kategorie "nicht optimiert" eingestuft wird. JS-Engines müssen ihr Bestes geben, um Code zu klassifizieren, insbesondere "heißen" Code, auf den sehr oft zugegriffen wird, und wenn Sie etwas Besonderes wie das Ändern tun __proto__
, werden sie Ihren Code überhaupt nicht optimieren.
In diesem Beitrag https://bugzilla.mozilla.org/show_bug.cgi?id=607863 werden speziell die aktuellen Implementierungen __proto__
und deren Unterschiede erläutert . Jede Implementierung macht es anders, weil es ein hartes und ungelöstes Problem ist. Alles in Javascript ist veränderbar, außer a.) Die Syntax b.) Hostobjekte (das DOM existiert technisch außerhalb von Javascript) und c.) __proto__
. Der Rest liegt vollständig in Ihren Händen und bei jedem anderen Entwickler, sodass Sie sehen können, warum __proto__
er wie ein schmerzender Daumen hervorsteht.
Es gibt eine Sache, __proto__
die dies ansonsten unmöglich macht: die Bezeichnung eines Objektprototyps zur Laufzeit getrennt von seinem Konstruktor. Dies ist ein wichtiger Anwendungsfall und einer der Hauptgründe, warum er __proto__
noch nicht tot ist. Es ist wichtig genug, dass dies ein ernstzunehmender Diskussionspunkt bei der Formulierung von Harmony war oder bald als ECMAScript 6 bekannt sein wird. Die Möglichkeit, den Prototyp eines Objekts während der Erstellung anzugeben, wird Teil der nächsten Version von Javascript sein Die Glocke, die __proto__
die Tage anzeigt , ist offiziell nummeriert.
Kurzfristig können Sie verwenden, __proto__
wenn Sie auf Browser abzielen, die dies unterstützen (nicht IE und kein IE wird dies jemals tun). Es ist wahrscheinlich, dass es in den nächsten 10 Jahren in Webkit und Moz funktioniert, da ES6 erst 2013 fertiggestellt wird.
Brendan Eich - re: Ansatz neuer Objektmethoden in ES5 :
Sorry, ... aber einstellbar __proto__
, abgesehen vom Anwendungsfall des Objektinitialisierers (dh bei einem neuen Objekt, das noch nicht erreichbar ist, analog zu Object.create von ES5), ist eine schreckliche Idee. Ich schreibe dies, nachdem ich es vor __proto__
über 12 Jahren entworfen und implementiert habe.
... das Fehlen einer Schichtung ist ein Problem (betrachten Sie JSON-Daten mit einem Schlüssel "__proto__"
). Schlimmer noch, die Veränderlichkeit bedeutet, dass Implementierungen nach zyklischen Prototypketten suchen müssen, um ein Iloooping zu vermeiden. [ständige Überprüfung auf unendliche Rekursion erforderlich]
Schließlich kann das Mutieren __proto__
eines vorhandenen Objekts nicht generische Methoden im neuen Prototypobjekt beschädigen, die möglicherweise nicht auf dem Empfängerobjekt (direkt) funktionieren können, dessen Objekt __proto__
festgelegt wird. Dies ist einfach eine schlechte Praxis, eine Form der absichtlichen Typverwirrung im Allgemeinen.