Warum ist die Erweiterung des DOM / der eingebauten Objektprototypen eine schlechte Idee?

15

Ich bin auf der Suche nach einer endgültigen Antwort darauf, warum das Erweitern von eingebauten Prototypen in der JS-Entwickler-Community so stark kritisiert wird. Ich verwende das Prototype JS-Framework seit einiger Zeit und finde es [1,2,3].each(doStuff)viel eleganter als $.each([1,2,3], doStuff). Ich weiß, dass es "Namespace-Verschmutzung" verursacht, aber ich verstehe immer noch nicht, warum es als eine schlechte Sache angesehen wird. Gibt es auch einen echten Leistungsabfall, der mit der Erweiterung von eingebauten Prototypen verbunden ist? Vielen Dank!

lxe
quelle
1
Eine Sache ist, dass for(var ... in ...)Schleifen durcheinander geraten, da auch Prototypfunktionen übergeben werden.
pimvdb
4
"schwer bestraft", wirklich ?! Guter Gott, Mann. Bist du in Ordnung?
Pixelbobby

Antworten:

12

Ich empfehle Ihnen, diesen Artikel zu lesen, der meiner Meinung nach ziemlich gut erklärt, warum das Erweitern von Objekten eine schlechte Idee ist, auch im Hinblick auf Prototype.

In Summe:

Fehlende Spezifikation

Die Belichtung von "Prototyp-Objekten" ist nicht Teil einer Spezifikation. [...] Damit die Implementierung vollständig mit DOM Level 2 übereinstimmt, müssen diese globalen Objekte Node, Element, HTMLElement usw. nicht verfügbar gemacht werden.

Hostobjekte haben keine Regeln

DOM-Objekte sind Host-Objekte. [...] Host-Objekte können diese internen Methoden mit jedem implementierungsabhängigen Verhalten implementieren, oder es kann sein, dass ein Host-Objekt nur einige interne Methoden und keine anderen implementiert.

[...] Das Verhalten interner Methoden ist implementierungsabhängig. [...] Per Definition arbeiten Sie mit etwas, das sich unvorhersehbar und völlig unberechenbar verhalten darf.

Möglichkeit von Kollisionen

In Anbetracht der großen Anzahl von Umgebungen, die heutzutage verwendet werden, ist es unmöglich festzustellen, ob bestimmte Objekte nicht bereits Teil eines DOM sind. [...]

Jedes benannte Formularsteuerelement beschattet Eigenschaften, die über die Prototypkette vererbt wurden. Die Wahrscheinlichkeit von Kollisionen und unerwarteten Fehlern bei Formularelementen ist noch höher.

Der Einsatz einer Präfixierungsstrategie kann das Problem lindern. Wird aber wohl auch extra Lärm bringen.

Leistungsaufwand

[...] Browser, die keine Elementerweiterungen unterstützen (z. B. IE 6, 7, Safari 2.x usw.), erfordern eine manuelle Objekterweiterung. Das Problem ist, dass die manuelle Erweiterung langsam, unpraktisch und nicht skalierbar ist.

Sobald Sie mit dem Erweitern von Elementen beginnen, muss die Bibliotheks-API höchstwahrscheinlich überall erweiterte Elemente zurückgeben. Daher können Abfragemethoden wie $$ jedes einzelne Element in einer Abfrage erweitern.

IE DOM ist ein Durcheinander

Wie im vorherigen Abschnitt gezeigt, ist die manuelle DOM-Erweiterung ein Durcheinander. Aber manuelle DOM-Erweiterung im IE ist noch schlimmer [...]

Bonus: Browser-Fehler

Jose Faeti
quelle
9

Ein weiterer Grund ist die Lesbarkeit / Wartbarkeit des Codes. Wenn ein anderer Entwickler (insbesondere ein Neuling) meinen Code liest und sieht [0, 1, 2].foo(...), dass er möglicherweise nicht weiß, was die foo-Methode ist oder wo er Dokumentation / Quelle dafür findet. Ist foo eine Erweiterung der Sprache, die von prototype.js oder einer anderen verwendeten Bibliothek oder einem anderen Teil meines Codes in einer anderen Datei hinzugefügt wurde, oder handelt es sich um eine native JavaScript-Methode, die sie nicht kannten? Sie müssen danach suchen und finden es möglicherweise nicht sofort (oder bei Konflikten finden sie möglicherweise nicht das richtige).

Beim jQuery-Ansatz $.foo(...)macht der Namespace der foo-Methode deutlich, wo sich ihre Definition / Dokumentation befindet, wenn Sie nicht wissen, was sie tut.

Bruce Harris
quelle
Die Auffindbarkeit, woher die Methoden stammen, ist für die Leser sehr wichtig. Obwohl ich nicht wirklich denke, dass jQuery ein gutes Beispiel ist, da das Dollarzeichen eine Herausforderung für die Suche darstellt, wenn Sie mit dem Lesen von Webcode beginnen und noch nicht wissen, was es ist.
Simon Feltman
4

Hier ist das grundlegende Problem: Was passiert, wenn Sie über zwei Tools verfügen, die Prototypen auf inkompatible Weise erweitern, oder die allgemein als Methoden bezeichneten Methoden so erweitern, dass sie unterschiedliche Ergebnisse liefern (dies ist ein spezielles Problem for...inin JavaScript), wodurch Code entsteht, der darauf angewiesen ist auf ihr normales Verhalten zu brechen?

Grundsätzlich sind es die gleichen Probleme, die Sie haben, wenn Sie globale Variablen missbrauchen. An sich passiert vielleicht nichts Schlimmes. Aber es macht Sie ärgerlich, wenn plötzlich zwei scheinbar voneinander getrennte Code-Teile aufeinander treten (und es ist schwierig, Fehler zu beheben, wenn dies passiert).

Natürlich ist prototype.js ziemlich bekannt, und die meisten Tools arbeiten mit der Funktionsweise. Ebenso bin ich sicher, dass es Fälle gibt, in denen die Erweiterung von Basisprototypen das Richtige ist. Aber Vorsicht ist geboten.


quelle
1

Ich bin mir nicht sicher, ob dies wirklich noch ein Problem ist, aber meiner Erfahrung nach war es mit früheren Versionen von Internet Explorer manchmal nicht möglich, bestimmte eingebaute Typen zu erweitern.


quelle
1

Hier gibt es zwei verschiedene Probleme. Die erste betrifft die allgemeine Erweiterung von integrierten Prototypen und die andere betrifft die Erweiterung von DOM-Prototypen. Die Argumente gegen die Erweiterung von eingebauten Prototypen:

  • Mögliche Konflikte: zwei Codeteile aus verschiedenen Quellen, die dieselbe Eigenschaft auf demselben Prototyp definieren
  • Nebenwirkungen: Erweitern Array.prototypeoder Object.prototypekann Folgewirkungen haben, z. B. das Hinzufügen der in einer for...inSchleife aufgezählten Erweiterungsmethoden

Für die Erweiterung von DOM-Prototypen gilt weiterhin das oben genannte mögliche Konfliktargument. Darüber hinaus sind DOM-Knoten Hostobjekte und unterliegen daher keiner der normalen Regeln für native JavaScript-Objekte. Sie können im Wesentlichen das tun, was sie möchten und sind nicht verpflichtet, sinnvolle Prototypobjekte bereitzustellen oder sogar zusätzliche ("expando") Eigenschaften zuzulassen. Verschiedene weirdnesses über Eigenschaften auf verschiedenen DOM - Objekten IE insbesondere macht von seinem Recht, die Bereitstellung keine Prototypen für DOM vor IE - Objekten 9 und mit (auch wenn Sie sind in der Regel OK Festlegen der Eigenschaften von Elementen, sofern nichts von Satz document.expandozu false.)

Tim Down
quelle