Warum wird document.write als „schlechte Praxis“ angesehen?

363

Ich weiß, dass dies document.writeals schlechte Praxis angesehen wird. und ich hoffe, eine Liste von Gründen zusammenstellen zu können, die einem Drittanbieter vorgelegt werden müssen, warum sie document.writebei der Implementierung ihres Analysecodes nicht verwendet werden sollten .

Bitte geben Sie document.writeunten Ihren Grund für die Behauptung als schlechte Praxis an.

FlySwat
quelle

Antworten:

243

Einige der schwerwiegenderen Probleme:

  • document.write (fortan DW) funktioniert in XHTML nicht

  • DW ändert das DOM nicht direkt und verhindert so weitere Manipulationen (versucht, Beweise dafür zu finden, aber es ist bestenfalls situativ)

  • DW, das ausgeführt wird, nachdem die Seite vollständig geladen wurde, überschreibt die Seite oder schreibt eine neue Seite oder funktioniert nicht

  • DW wird ausgeführt, wenn es auftritt: Es kann nicht an einem bestimmten Knotenpunkt injiziert werden

  • DW schreibt effektiv serialisierten Text, was nicht die konzeptionelle Funktionsweise des DOM ist und eine einfache Möglichkeit zum Erstellen von Fehlern darstellt (.innerHTML hat das gleiche Problem).

Es ist weitaus besser, die sicheren und DOM-freundlichen DOM-Manipulationsmethoden zu verwenden

Annakata
quelle
39
-1, es ändert absolut das DOM. Alles andere ist in Ordnung. Ich verstehe zwar den Drang, sich auf Strukturen und Methoden zu verlassen, die Sie vor Schaden bewahren können, aber dies kann ein Fall sein, bei dem das Baby mit dem Badewasser weggeworfen wird.
CGP
7
FireBug ist keine echte Darstellung des DOM. Es ist Mozillas Versuch, HTML in ein DOM zu analysieren. In der Firebug-DOM-Ansicht kann HTML-Code völlig fehlerhaft aussehen.
FlySwat
8
Das DOM ist die Datenstruktur, die zum Rendern der Seite verwendet wird, und als solche das Alpha und das Omega dessen, was der Benutzer auf der Seite sieht. Sie haben Recht, dass HTML! = DOM, aber es ist unerheblich für die Frage, ob das DOM von DW geändert wird oder nicht. Wenn DW das DOM nicht geändert hat, wird der Bildschirm nicht angezeigt. Dies gilt für alle Browser und gilt immer, solange das DOM zum Rendern der Seite verwendet wird.
CGP
8
"DW wird ausgeführt, wo es vorkommt" - nicht immer ein Nachteil, in der Tat könnte es als Vorteil für bestimmte Dinge angesehen werden, z. B. das Hinzufügen von Skriptelementen (eigentlich das einzige, wofür ich DW verwenden würde, und selbst dann würde ich zweimal überlegen) .
nnnnnn
7
@ RicardoRivaldo Ja, sie tun es, wenn document.writeaufgerufen wird, nachdem das Dokument
vollständig geladen wurde
124

Es ist eigentlich nichts falsch an document.writesich. Das Problem ist, dass es wirklich leicht ist, es zu missbrauchen. Grob sogar.

In Bezug auf Anbieter, die Analytics-Code bereitstellen (wie Google Analytics), ist dies für sie die einfachste Möglichkeit, solche Snippets zu verteilen

  1. Es hält die Skripte klein
  2. Sie müssen sich nicht darum kümmern, bereits eingerichtete Onload-Ereignisse zu überschreiben oder die erforderliche Abstraktion einzuschließen, um Onload-Ereignisse sicher hinzuzufügen
  3. Es ist extrem kompatibel

Solange Sie nicht versuchen, es zu verwenden, nachdem das Dokument geladen wurde ,document.writeist es meiner bescheidenen Meinung nach nicht von Natur aus böse.

Peter Bailey
quelle
3
document.write macht wirklich schreckliche Dinge mit den HTML-Parsern und ist nur in einfachen Fällen "extrem kompatibel".
olliej
27
Wie das Einfügen eines Analytics-Tags? Das ist schließlich Teil der ursprünglichen Frage. Und mit extrem kompatibel meine ich nur die rohe Browserunterstützung für die document.write-Methode.
Peter Bailey
Alles, was mit den neuesten Versionen von Chrome / IE / Safari / Opera / FireFox funktioniert, wird als kompatibel angesehen.
Pacerier
2
Onload-Ereignisse überschreiben? Und wofür addEventListener?
M93a
Chrome führt keine document.writeAufrufe aus, die ein Skript einfügen, wenn bestimmte Bedingungen erfüllt sind.
Flimm
44

Eine andere legitime Verwendung von document.write stammt aus dem Beispiel HTML5 Boilerplate index.html .

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>

Ich habe auch die gleiche Technik für die Verwendung der JSON-Analyse- / Stringify- Polyfüllung json2.js gesehen (wird von IE7 und darunter benötigt ).

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>
Kevin Hakanson
quelle
11
Keine schlechte Verwendung hier, aber immer noch "besser", um DOM-Manipulationsfunktionen zu verwenden - selbst Google tut dies für Google Analytics. Snippet ist da .
BMiner
8
@BMiner Wenn Sie ein scriptElement über DOM-Manipulation einfügen , wird es synchron geladen? Es sei denn, es ist kein Ersatz.
John Dvorak
2
@ JanDvorak - Guter Punkt; Bei Verwendung von DOM-Manipulationen laden Browser das Skript im Allgemeinen asynchron. Mit dem onloadDOM-Ereignis können Sie bestimmen, wann das asynchron geladene Skript zur Verwendung verfügbar ist.
BMiner
1
@ JanDvorak Es wird synchron geladen, wenn es nicht extern ist (nicht hat src) . Andernfalls wird es "so bald wie möglich" asynchron ausgeführt.
Oriol
1
Dies kann immer noch nicht funktionieren, da Chrome sich absichtlich weigert, document.writeAnrufe auszuführen , die <script>Tags einfügen, wenn der Benutzer eine 2G-Verbindung hat. Siehe developer.google.com/web/updates/2016/08/…
Flimm
42

Es kann Ihre Seite blockieren

document.writefunktioniert nur, während die Seite geladen wird; Wenn Sie es nach dem Laden der Seite aufrufen, wird die gesamte Seite überschrieben.

Dies bedeutet effektiv, dass Sie es von einem Inline-Skriptblock aus aufrufen müssen. Dadurch wird verhindert, dass der Browser Teile der folgenden Seite verarbeitet. Skripte und Bilder werden erst heruntergeladen, wenn der Schreibblock fertig ist.

Sean McMillan
quelle
31

Profi:

  • Dies ist der einfachste Weg, um Inline-Inhalte aus einem externen Skript (in Ihren Host / Ihre Domain) einzubetten.
  • Sie können den gesamten Inhalt in einem Frame / Iframe überschreiben. Ich habe diese Technik häufig für Menü- / Navigationselemente verwendet, bevor modernere Ajax-Techniken allgemein verfügbar waren (1998-2002).

Con:

  • Die Rendering-Engine wird so serialisiert, dass sie angehalten wird, bis das externe Skript geladen wird. Dies kann viel länger dauern als bei einem internen Skript.
  • Es wird normalerweise so verwendet, dass das Skript innerhalb des Inhalts platziert wird, was als schlechte Form angesehen wird.
Tracker1
quelle
3
Es gibt mehr Nachteile als das. Beispielsweise lehnt Google Chrome die Ausführung ab document.write, bei der <script>unter bestimmten Umständen Tags erstellt werden. developer.google.com/web/updates/2016/08/…
Flimm
@Flimm es ist erwähnenswert, dein Kommentar ist über 8 Jahre nach meiner Antwort und dies fast 3 Jahre später. Ja, es gibt noch andere Nachteile ... und ich wäre überrascht, wenn document.write selbst nicht verschwindet ... sowie möglicherweise einige andere stark missbrauchte Schnittstellen.
Tracker1
10

Hier ist mein Zwei-Pence-Wert, den Sie im Allgemeinen nicht verwenden sollten document.write für schweres Heben verwenden, aber es gibt einen Fall, in dem er definitiv nützlich ist:

http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html

Ich habe dies kürzlich beim Versuch entdeckt, eine AJAX-Slider-Galerie zu erstellen. Ich habe zwei verschachtelte Divs erstellt und width/ heightund overflow: hiddenauf das Äußere angewendet<div> mit JS . Dies war so, dass für den Fall, dass der Browser JS deaktiviert hatte, das div schwebte, um die Bilder in der Galerie aufzunehmen - eine nette, anmutige Verschlechterung.

Die Sache ist, wie im obigen Artikel, dass diese JS-Entführung des CSS erst nach dem Laden der Seite einsetzte und beim Laden des Divs einen kurzen Blitz verursachte. Also musste ich eine CSS-Regel schreiben oder ein Blatt einfügen, wenn die Seite geladen wurde.

Natürlich funktioniert dies in XHTML nicht, aber da XHTML eine tote Ente zu sein scheint (und im IE als Tag-Suppe dargestellt wird), lohnt es sich möglicherweise, Ihre Wahl von DOCTYPE neu zu bewerten ...

Sunwukung
quelle
7

Es überschreibt den Inhalt der Seite, was der offensichtlichste Grund ist, aber ich würde es nicht "schlecht" nennen.

Es hat nur wenig Sinn, wenn Sie nicht ein ganzes Dokument mit JavaScript erstellen. In diesem Fall können Sie mit document.write beginnen.

Trotzdem nutzen Sie das DOM nicht wirklich, wenn Sie document.write verwenden. Sie geben nur einen Textklecks in das Dokument ein, also würde ich sagen, dass es eine schlechte Form ist.

Aleemb
quelle
2
Eine Klarstellung: document.write fügt Inhalte auf der Seite ein, überschreibt sie nicht.
Peter Dolberg
5
@Peter überschreibt den Inhalt, wenn Sie ihn nach dem Laden des Dokuments aufrufen. Ich vermute, das ist es, was Aleemb bedeutet.
Matthew Crumley
2
Schlagen Sie vor, die einzelnen DOM-Knoten stattdessen manuell im Code zu erstellen, anstatt nur so etwas zu tun div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";? Das scheint viel unnötigen und weniger lesbaren Code zu produzieren. Es ist auch das genaue Gegenteil des Ansatzes, den John Resig und andere JS-Entwickler vertreten.
Lèse Majesté
7

Es bricht Seiten mit XML-Rendering (wie XHTML-Seiten).

Am besten : Einige Browser wechseln wieder zum HTML-Rendering und alles funktioniert einwandfrei.

Wahrscheinlich : Einige Browser deaktivieren die Funktion document.write () im XML-Rendering-Modus.

Das Schlimmste : Einige Browser lösen bei Verwendung der Funktion document.write () einen XML-Fehler aus.

Vincent Robert
quelle
6

Aus dem Kopf:

  1. document.writemuss beim Laden von Seiten oder Körpern verwendet werden. Wenn Sie das Skript also zu einem anderen Zeitpunkt verwenden möchten, um Ihr Seiteninhaltsdokument zu aktualisieren, ist das Schreiben so gut wie nutzlos.

  2. Technisch document.writewerden nur HTML-Seiten aktualisiert, nicht XHTML / XML. IE scheint diese Tatsache ziemlich zu verzeihen, andere Browser jedoch nicht.

http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite

brendan
quelle
9
IE verzeiht, weil es XHTML nicht unterstützt. In diesem Fall funktioniert document.write wahrscheinlich nicht mehr (natürlich nur in XHTML).
Matthew Crumley
2
XHTML ist im Web irrelevant. Auch Seiten mit einer strengen XHTML doctype werden als XML in diesem Zusammenhang Browser - Entwickler Vertrauen Seite Autoren nicht wirklich behandelt nicht , dass viel.
RobG
4

document.writeIn bestimmten Fällen blockiert Chrome möglicherweise das Einfügen eines Skripts. In diesem Fall wird diese Warnung in der Konsole angezeigt:

Ein parserblockierendes, originalübergreifendes Skript ... wird über document.write aufgerufen. Dies kann vom Browser blockiert werden, wenn das Gerät eine schlechte Netzwerkverbindung aufweist.

Verweise:

TrueWill
quelle
3

Browserverletzung

.writewird als Browserverletzung angesehen, da der Parser beim Rendern der Seite angehalten wird. Der Parser erhält die Nachricht, dass das Dokument geändert wird. Daher wird es blockiert, bis JS seinen Prozess abgeschlossen hat. Erst zu diesem Zeitpunkt wird der Parser fortgesetzt.

Performance

Die größte Folge der Anwendung einer solchen Methode ist eine verminderte Leistung. Das Laden des Seiteninhalts durch den Browser dauert länger. Die nachteilige Reaktion auf die Ladezeit hängt davon ab, was in das Dokument geschrieben wird. Sie werden keinen großen Unterschied feststellen, wenn Sie <p>dem DOM ein Tag hinzufügen , anstatt ein Array mit 50 Verweisen auf JavaScript-Bibliotheken zu übergeben (was ich im Arbeitscode gesehen habe und zu einer Verzögerung von 11 Sekunden geführt habe) Dies hängt natürlich auch von Ihrer Hardware ab.

Alles in allem ist es am besten, sich von dieser Methode fernzuhalten, wenn Sie helfen können.

Weitere Informationen finden Sie unter Eingreifen gegen document.write ()

Arielle Adams
quelle
3

Basierend auf der Analyse erfolgt durch Google-Chrome Dev Tools' Leuchtturm Audit ,

Für Benutzer mit langsamen Verbindungen können externe Skripte, die dynamisch über injiziert werden, document.write()das Laden der Seite um mehrere zehn Sekunden verzögern.

Geben Sie hier die Bildbeschreibung ein

Sudip Bhandari
quelle
2
  • Ein einfacher Grund warum document.write für eine schlechte Praxis ist, dass Sie kein Szenario finden können, in dem Sie keine bessere Alternative finden können.
  • Ein weiterer Grund ist, dass Sie mit Zeichenfolgen anstelle von Objekten arbeiten (es ist sehr primitiv).
  • Es wird nur an Dokumente angehängt.
  • Es hat nichts von der Schönheit des MVC- Musters (Model-View-Controller) .
  • Es ist viel leistungsfähiger, dynamische Inhalte mit ajax + jQuery oder angleJS zu präsentieren .
Anders Lindén
quelle
Wie werden Sie das lösen, was @sunwukung in seiner obigen Antwort beschreibt? Ich bin damit einverstanden Sie könnte es mit DOM - Manipulationen zu lösen, sondern als DOM - Manipulationen gehen, ist es schwer FuOC manchmal zu vermeiden , ohne document.write.
Bert Bruynooghe
Ist FUOC kein Problem mehr?
Anders Lindén
1

Man kann sich document.write () (und .innerHTML) als Auswertung einer Quellcode-Zeichenfolge vorstellen. Dies kann für viele Anwendungen sehr praktisch sein. Wenn Sie beispielsweise HTML-Code als Zeichenfolge aus einer Quelle erhalten, ist es praktisch, ihn nur "auszuwerten".

Im Kontext von Lisp wäre die DOM-Manipulation wie die Manipulation einer Listenstruktur, z. B. Erstellen der Liste (orange), indem Sie Folgendes tun:

(cons 'orange '())

Und document.write () wäre wie das Auswerten einer Zeichenfolge, z. B. das Erstellen einer Liste durch Auswerten einer Quellcode-Zeichenfolge wie folgt:

(eval-string "(cons 'orange '())")

Lisp bietet außerdem die sehr nützliche Möglichkeit, Code mithilfe von Listenmanipulationen zu erstellen (z. B. mithilfe des "DOM-Stils" zum Erstellen eines JS-Analysebaums). Dies bedeutet, dass Sie eine Listenstruktur mit dem "DOM-Stil" anstelle des "Zeichenfolgenstils" erstellen und diesen Code dann ausführen können, z. B.:

(eval '(cons 'orange '()))

Wenn Sie Codierungswerkzeuge wie einfache Live-Editoren implementieren, ist es sehr praktisch, eine Zeichenfolge schnell auswerten zu können, z. B. mit document.write () oder .innerHTML. Lisp ist in diesem Sinne ideal, aber Sie können auch in JS sehr coole Sachen machen, und viele Leute machen das, wie http://jsbin.com/

Mikael Kindborg
quelle
1

Die Nachteile von document.write hängen hauptsächlich von diesen drei Faktoren ab:

a) Umsetzung

Das document.write () wird meistens verwendet, um Inhalte auf den Bildschirm zu schreiben, sobald diese Inhalte benötigt werden. Dies bedeutet, dass dies überall geschieht, entweder in einer JavaScript-Datei oder in einem Skript-Tag in einer HTML-Datei. Da das Skript-Tag an einer beliebigen Stelle in einer solchen HTML-Datei platziert wird, ist es eine schlechte Idee, document.write () -Anweisungen in Skriptblöcken zu haben, die mit HTML in einer Webseite verflochten sind.

b) Rendern

Gut gestalteter Code nimmt im Allgemeinen dynamisch generierten Inhalt auf, speichert ihn im Speicher und manipuliert ihn weiter, während er den Code durchläuft, bevor er schließlich auf den Bildschirm gespuckt wird. Um den letzten Punkt im vorhergehenden Abschnitt zu wiederholen, wird das Rendern von Inhalten an Ort und Stelle möglicherweise schneller gerendert als andere Inhalte, auf die man sich verlassen kann, aber es ist möglicherweise nicht für den anderen Code verfügbar, für den wiederum der Inhalt zur Verarbeitung gerendert werden muss. Um dieses Dilemma zu lösen, müssen wir das document.write () loswerden und es richtig implementieren.

c) Unmögliche Manipulation

Sobald es geschrieben ist, ist es fertig und vorbei. Wir können nicht zurückgehen, um es zu manipulieren, ohne auf das DOM zu tippen.

user3167857
quelle
1

Ich denke nicht, dass die Verwendung von document.write eine schlechte Praxis ist. In einfachen Worten ist es wie eine Hochspannung für unerfahrene Menschen. Wenn Sie es falsch verwenden, werden Sie gekocht. Es gibt viele Entwickler, die diese und andere gefährliche Methoden mindestens einmal angewendet haben und sich nie wirklich mit ihren Fehlern befassen. Wenn stattdessen etwas schief geht, steigen sie einfach aus und verwenden etwas Sichereres. Das sind diejenigen, die solche Aussagen über eine "schlechte Praxis" machen.

Es ist wie beim Formatieren einer Festplatte, wenn Sie nur wenige Dateien löschen und dann sagen müssen, dass das Formatieren der Festplatte eine schlechte Praxis ist.

Edgars WEBHAUS
quelle
-3

Ich denke, das größte Problem ist, dass alle Elemente, die über document.write geschrieben wurden, am Ende der Elemente der Seite hinzugefügt werden. Dies ist bei modernen Seitenlayouts und AJAX selten der gewünschte Effekt. (Sie müssen berücksichtigen, dass die Elemente im DOM zeitlich begrenzt sind und dass die Ausführung des Skripts das Verhalten beeinflussen kann.)

Es ist viel besser, ein Platzhalterelement auf der Seite festzulegen und dann das innere HTML zu bearbeiten.

BnWasteland
quelle
15
Das ist nicht wahr. document.write fügt den Inhalt nicht am Ende der Seite hinzu, als wäre es ein Anhang. Sie sind an Ort und Stelle geschrieben.
Peter Bailey
1
@ Peter Bailey, ich weiß, dass dies ein alter Thread ist, aber das sollte wirklich nicht herabgestimmt werden. Ob es angehängt wird oder nicht, hängt davon ab, ob document.write () während des Ladens der Seite inline ausgeführt wird. Wenn es von einer Funktion aufgerufen wird, nachdem die Seite geladen wurde, ersetzt das erste document.write () den gesamten Text und nachfolgende Aufrufe werden an ihn angehängt.
Octopus
3
@ Octopus Ja, aber das ist umständlich. In diesem Szenario wird es nur angehängt, weil ein neues Dokument vorhanden ist. Es ist immer noch nicht korrekt zu sagen, dass "document.write () anhängt". Ja, es ist eine alte Antwort und eine alte Ablehnung, aber ich stehe immer noch dazu.
Peter Bailey
Das ist gut. Ich sprach ungenau. Ich hätte es schon vor langer Zeit bearbeitet, aber oben gibt es eine viel bessere Antwort. Ich möchte jedoch darauf hinweisen, dass "an Ort und Stelle geschrieben" ebenso ungenau ist.
BnWasteland