Warum mutiert die [[prototype]] von einem Objekt schlecht für die performance?
Aus der MDN docs für die standard setPrototypeOf
- Funktion sowie die nicht-standard - __proto__
Eigenschaft:
Mutiert die [[Prototype]] von einem Gegenstand, egal wie dies erreicht wird, ist dringend abzuraten, denn es ist sehr langsam und unvermeidlich verlangsamt sich anschließende Ausführung in der modernen JavaScript-Implementierungen.
Mit Function.prototype
um Eigenschaften hinzuzufügen ist die Möglichkeit zum hinzufügen von member-Funktionen, um javascript-Klassen. Dann wie im folgenden gezeigt:
function Foo(){}
function bar(){}
var foo = new Foo();
//This is bad:
//foo.__proto__.bar = bar;
//But this is okay
Foo.prototype.bar = bar;
//Both cause this to be true:
console.log(foo.__proto__.bar == bar); //true
Warum ist foo.__proto__.bar = bar;
schlecht? Wenn Ihr bad ist nicht Foo.prototype.bar = bar;
genauso schlimm?
Warum dann diese Warnung: es ist sehr langsam und unvermeidlich verlangsamt sich anschließende Ausführung in der modernen JavaScript-Implementierungen. Sicherlich Foo.prototype.bar = bar;
ist nicht so schlimm.
Update Vielleicht durch mutation gemeint ist die Umwidmung. Siehe Antwort akzeptiert.
__proto__
ist ein nicht nicht-standard-Eigenschaft .. so dass aus dem Weg, es wäre schön, finden Sie die Antworten, die auf die performance-Frage direkt: Warum ist es "..sehr langsam und unvermeidlich verlangsamt sich anschließende Ausführung in der modernen JavaScript-Implementierungen"?danke. Das war meine Absicht. Aktualisierte Frage zu sein, mehr durch explizite Nennung des neuen der standard Weg.
Ich kann mir vorstellen, dass Sie beide haben das gleiche problem. Es scheint, wie die JS-engine benötigen würde, um "flush" zwischengespeicherte Eigenschaft Auflösungen oder andere kompiliert/intermediate IL für alle angekettet (abgeleitete) Objekte.
Vielleicht. Obwohl ich nicht einverstanden mit dieser Antwort, wie es scheint, zu Rock Problemen mit expliziten mutation (kann man mutieren, ohne
__proto__
, wie gezeigt) und impliziert, dass es keine solchen Optimierungen auftreten (die Auswirkungen auf die Leistung wrt. Mutationen nicht existent).Ich fand die Frage und die entsprechende Antwort, die ich suchte: Soll ich default-Werte der Attribute, die auf den Prototyp, um Platz zu sparen? zwar nicht vollständig Verwandte ich denke, das ist einer der Gründe, warum sollten Sie das nicht tun.
InformationsquelleAutor basarat | 2014-05-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nicht. Beide tun das gleiche (wie
foo.__proto__ === Foo.prototype
), und beide sind in Ordnung. Sie sind nur die Schaffung einesbar
Eigenschaft auf dieObject.getPrototypeOf(foo)
Objekt.Was die Aussage bezieht, ist die Zuweisung an die
__proto__
Immobilie selbst:Die Warnung am
- Objekt.prototype
- Seite geht mehr ins detail:Sie einfach, dass ändern der Prototyp-Kette von einem bereits vorhandenen Objekt tötet Optimierungen. Stattdessen sollen Sie sich ein neues Objekt zu erstellen mit verschiedenen Prototyp-Kette über
Object.create()
.Konnte ich nicht finden, eine explizite Referenz, aber wenn wir betrachten, wie V8-hidden-Klassen umgesetzt werden, können wir sehen, was gehen könnte. Beim Wechsel der Prototypkette des Objekts, seine internen Veränderungen - es wird nicht einfach werden, eine Unterklasse wie beim hinzufügen einer Eigenschaft, sondern komplett getauscht. Es bedeutet, dass alle Eigentums-lookup-Optimierungen sind geleert, und vorkompilierten code, müssen verworfen werden. Oder es fällt einfach wieder zu nicht optimierten code.
Einige Bemerkenswerte Zitate:
Brendan Eich (Sie kennt ihn) sagte,
Brian Hackett (Mozilla) sagte:
Jeff Walden, sagte:
Erik Corry (Google) sagte:
Eric Faust (Mozilla) sagte
Nach dieser durch mutating Sie bedeuten, dass neu zuweisen. In diesem Fall mit
fred = Object.create(Object.prototype)
sollte genau so schlimm. Aber Sie specifially sagen, das gute :Instead, create the object with the desired [[Prototype]] using Object.create.
. Ich glaube, Sie haben Recht wenn. Sie haben möglicherweise optimiertObject.create
.Es ist eine erhebliche performance-Unterschied zwischen Objekt.erstellen und die proto : jsperf.com/proto-vs-object-create2 vielen Dank für Ihre Zeit
Ich verzichtete darauf schreiben ein jsperf, denn diese sind schwer zu schreiben und Sie nicht wissen, was genau Sie testen (oder ob das, was Sie testen, ist relevant im echten code, oder du hast eine leicht optimisable). Der ursprüngliche Fall, dass Sie verlinkt hatten einige gute tests im letzteren Revisionen. Für den test habe ich aktualisiert mit einem statischen Ziel-Prototypen von neuen Objekten, der zeigt, was den Unterschied sogar noch besser.
Danke, behoben
InformationsquelleAutor Bergi
__proto__
/setPrototypeOf
sind nicht die gleichen wie die Zuordnung zu den object-Prototyp. Zum Beispiel, wenn Sie eine Funktion/Objekt mit den Mitgliedern zugeordnet es:Alle scheinen sich nur auf das Prototyp, und vergessen, dass Funktionen können den Mitgliedern zugeordnet und instanziiert nach der mutation. Es gibt derzeit keinen anderen Weg, dies zu tun, ohne mit
__proto__
/setPrototypeOf
. Kaum jemand verwenden Sie einen Konstruktor ohne die Möglichkeit der Vererbung von einem Elternteil Konstruktor-Funktion, undObject.create
fehl zu dienen.Und plus, das sind zwei
Object.create
Anrufe, die an die Gegenwart, ist gottlos langsam in V8 (beide browser und Knoten), die macht__proto__
eine tragfähige WahlInformationsquelleAutor pocesar
Ja .Prototyp= ist genauso schlecht, daher ist die Formulierung "egal, wie es erreicht wird". Prototyp ist ein pseudo-Objekt für die Erweiterung der Funktionalität auf Klassen-Niveau. Seine dynamische Natur verlangsamt die Skript-Ausführung. Das hinzufügen einer Funktion, die auf die Instanz-Ebene, auf der anderen Seite, ist deutlich weniger Aufwand.
Adding a function on the instance level...incurs far less overhead.
- bis Sie viele Instanzen.Mehr Kontext ist nötig. Von meinem Verständnis der verlinkten Ressourcen, die es speziell bezieht sich auf die mutation der
[prototype]
Objekt. Als solche, die Zuordnung zuFn.prototype
ist nicht "genauso schlimm", weil es Kopie erstellen. (Die Frage konzentriert sich auf mutating der Prototyp-Objekt.)InformationsquelleAutor Schien
Hier ist ein benchmark mithilfe von Knoten -
v6.11.1
NormalClass: Eine normale Klasse, bei dem der Prototyp nicht bearbeitet
PrototypeEdited: A-Klasse mit dem Prototyp bearbeitet (die
test()
Funktion Hinzugefügt wird)PrototypeReference: Eine Klasse mit dem zusätzlichen Prototyp-Funktion
test()
wer referer, um eine externe variableErgebnisse :
Wie Sie sehen können, der Prototyp bearbeitet-Klasse ist ein Weg, schneller als die normale Klasse. Der Prototyp, der hat eine variable, die sich auf einem externen ist die langsamste, aber das ist eine interessante Art und Weise zu Bearbeiten Prototypen mit bereits instantied variable
Quelle :
.__proto__
oder rufenObject.setProtottypeOf()
, also die benchmark, während interessant, ist irrelevant für die gestellte Frage.InformationsquelleAutor Simon Et la famille