Pourquoi document.write est-il considéré comme une «mauvaise pratique»?


364

Je sais que document.writec'est considéré comme une mauvaise pratique; et j'espère compiler une liste de raisons de soumettre à un fournisseur tiers pourquoi ils ne devraient pas utiliser document.writedans les implémentations de leur code analytique.

Veuillez indiquer document.writeci-dessous la raison de votre réclamation en tant que mauvaise pratique.

Réponses:


243

Quelques-uns des problèmes les plus graves:

  • document.write (dorénavant DW) ne fonctionne pas en XHTML

  • DW ne modifie pas directement le DOM, empêchant toute manipulation supplémentaire (en essayant d'en trouver la preuve, mais c'est au mieux la situation)

  • DW exécuté après le chargement de la page écrasera la page, ou écrit une nouvelle page, ou ne fonctionnera pas

  • DW s'exécute là où il est rencontré: il ne peut pas injecter à un point de nœud donné

  • DW écrit effectivement du texte sérialisé, ce qui n'est pas la façon dont le DOM fonctionne conceptuellement, et c'est un moyen facile de créer des bogues (.innerHTML a le même problème)

Il vaut bien mieux utiliser les méthodes de manipulation DOM sûres et conviviales DOM


39
-1, il modifie absolument le DOM. Tout le reste va bien. Bien que je comprenne l'envie de dépendre de la structure et des méthodes qui peuvent vous protéger du mal, il peut s'agir de jeter le bébé avec l'eau du bain.
cgp

7
FireBug n'est pas une véritable représentation du DOM. C'est la tentative de Mozilla d'analyser le HTML dans un DOM. Vous pouvez avoir un HTML totalement cassé dans la vue DOM Firebug.
FlySwat

8
Le DOM est la structure de données utilisée pour rendre la page et en tant que tel est l'alpha et l'oméga de ce que l'utilisateur voit sur la page. Vous avez raison que HTML! = DOM, mais cela n'a pas d'importance si le DOM est modifié par DW ou non. Si DW n'a pas modifié le DOM, vous ne voyez pas l'écran - cela est vrai de tous les navigateurs et le sera toujours tant que le DOM est utilisé pour rendre la page.
cgp

8
"DW s'exécute là où il est rencontré" - pas toujours un inconvénient, en effet, cela pourrait être considéré comme un avantage pour certaines choses, par exemple, l'ajout d'éléments de script (en fait à peu près la seule chose pour laquelle j'utiliserais DW, et même alors j'y réfléchirais à deux fois) .
nnnnnn

7
@RicardoRivaldo Oui, ils le font, si document.writeest appelé une fois le chargement du document terminé
Izkata

124

Il n'y a en fait rien de mal en document.writesoi. Le problème est qu'il est vraiment facile d'en abuser. Grossièrement, même.

En ce qui concerne les fournisseurs fournissant du code analytique (comme Google Analytics), c'est en fait le moyen le plus simple pour eux de distribuer de tels extraits

  1. Il garde les scripts petits
  2. Ils n'ont pas à se soucier de remplacer les événements de charge déjà établis ou d'inclure l'abstraction nécessaire pour ajouter des événements de charge en toute sécurité
  3. C'est extrêmement compatible

Tant que vous n'essayez pas de l'utiliser après le chargement du document , cedocument.writen'est pas intrinsèquement mauvais, à mon humble avis.


3
document.write fait des choses vraiment horribles aux analyseurs html et n'est "extrêmement compatible" que dans des cas simples.
olliej

27
Vous aimez l'insertion d'une balise d'analyse? Cela fait, après tout, partie de la question initiale. Et par extrêmement compatible, je veux dire pour le support de navigateur brut pour la méthode document.write.
Peter Bailey

Tout ce qui fonctionne avec les dernières versions de Chrome / IE / Safari / Opera / FireFox est considéré comme compatible.
Pacerier

2
Ignorer les événements de surcharge? Et à quoi ça sert addEventListener?
m93a

Chrome n'exécutera pas d' document.writeappels qui insèrent un script lorsque certaines conditions sont remplies.
Flimm

44

Une autre utilisation légitime de document.writeprovient de l' exemple 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>

J'ai également vu la même technique pour utiliser le polyfill json2.js JSON parse / stringify ( requis par IE7 et ci-dessous ).

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>

11
Pas mal ici, mais toujours "mieux" pour utiliser les fonctions de manipulation DOM - même Google le fait pour Google Analytics. L'extrait est ici .
BMiner

8
@BMiner si vous insérez un scriptélément via une manipulation DOM, est-il chargé de manière synchrone? Sauf si c'est le cas, ce n'est pas un remplacement.
John Dvorak

2
@JanDvorak - Bon point; lors de l'utilisation de manipulations DOM, les navigateurs chargent généralement le script de manière asynchrone. Vous pouvez utiliser l' onloadévénement DOM pour déterminer quand le script chargé de manière asynchrone est disponible pour utilisation.
BMiner

1
@JanDvorak Il est chargé de manière synchrone s'il n'est pas externe (ne l'a pas src) . Sinon, il sera exécuté "dès que possible", de manière asynchrone.
Oriol

1
Cela peut encore se casser, car Chrome refusera délibérément d'exécuter des document.writeappels qui insèrent des <script>balises si l'utilisateur est sur une connexion 2G. Voir developers.google.com/web/updates/2016/08/…
Flimm

42

Cela peut bloquer votre page

document.writene fonctionne que pendant le chargement de la page; Si vous l'appelez après le chargement de la page, il écrasera la page entière.

Cela signifie que vous devez l'appeler à partir d'un bloc de script en ligne - et cela empêchera le navigateur de traiter les parties de la page qui suivent. Les scripts et les images ne seront pas téléchargés tant que le bloc d'écriture n'est pas terminé.


32

Pro:

  • C'est le moyen le plus simple d'incorporer du contenu en ligne à partir d'un script externe (à votre hôte / domaine).
  • Vous pouvez remplacer tout le contenu dans un cadre / iframe. J'utilisais beaucoup cette technique pour les éléments de menu / navigation avant que les techniques Ajax plus modernes ne soient largement disponibles (1998-2002).

Con:

  • Il sérialise le moteur de rendu pour faire une pause jusqu'à ce que ledit script externe soit chargé, ce qui pourrait prendre beaucoup plus de temps qu'un script interne.
  • Il est généralement utilisé de telle manière que le script est placé dans le contenu, qui est considéré comme de mauvaise forme.

3
Il y a plus d'inconvénients que ça. Par exemple, Google Chrome refusera d'exécuter document.writequi crée une <script>balise dans certaines circonstances. developers.google.com/web/updates/2016/08/…
Flimm

@Flimm, il est à noter, votre commentaire est plus de 8 ans après ma réponse et cela presque 3 ans plus tard. Ouais, il y a d'autres inconvénients ... et je serais surpris si document.write lui-même ne disparaisse pas ... ainsi que peut-être d'autres interfaces très mal utilisées.
Tracker1

10

Voici ma valeur de deux cents, en général, vous ne devriez pas l'utiliser document.writepour soulever des charges lourdes, mais il y a un cas où il est certainement utile:

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

J'ai découvert cela récemment en essayant de créer une galerie de curseurs AJAX. J'ai créé deux divisions imbriquées et appliqué width/ heightet overflow: hiddenà l'extérieur <div>avec JS. C'était ainsi que dans le cas où le navigateur avait désactivé JS, le div flottait pour accueillir les images dans la galerie - une belle dégradation gracieuse.

La chose est, comme avec l'article ci-dessus, ce détournement JS du CSS n'a pas démarré jusqu'à ce que la page soit chargée, provoquant un flash momentané pendant le chargement du div. J'avais donc besoin d'écrire une règle CSS, ou d'inclure une feuille, comme la page chargée.

Évidemment, cela ne fonctionnera pas dans XHTML, mais comme XHTML semble être quelque chose d'un canard mort (et s'affiche comme soupe de tag dans IE), il pourrait être utile de réévaluer votre choix de DOCTYPE ...


7

Il écrase le contenu de la page, ce qui est la raison la plus évidente, mais je n'appellerais pas cela "mauvais".

Il n'a tout simplement pas beaucoup d'utilité, sauf si vous créez un document entier en utilisant JavaScript, auquel cas vous pouvez commencer avec document.write.

Même ainsi, vous ne tirez pas vraiment parti du DOM lorsque vous utilisez document.write - vous videz simplement une goutte de texte dans le document, donc je dirais que c'est une mauvaise forme.


2
Une précision: document.write insère le contenu sur la page, il ne le remplace pas.
Peter Dolberg

5
@Peter, il écrase le contenu si vous l'appelez après le chargement du document. Je suppose que c'est ce que signifie aleemb.
Matthew Crumley

2
Suggérez-vous plutôt de créer manuellement les nœuds DOM individuels dans du code plutôt que de simplement faire quelque chose comme div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";? Cela semble produire beaucoup de code inutile et moins lisible. C'est aussi l'opposé exact de l'approche préconisée par John Resig et d'autres développeurs JS.
Lèse majesté

7

Il casse les pages en utilisant le rendu XML (comme les pages XHTML).

Meilleur : certains navigateurs reviennent au rendu HTML et tout fonctionne bien.

Probable : certains navigateurs désactivent la fonction document.write () en mode de rendu XML.

Pire : certains navigateurs déclenchent une erreur XML chaque fois que vous utilisez la fonction document.write ().


6

Du haut de ma tête:

  1. document.writedoit être utilisé dans le chargement de page ou le chargement de corps. Donc, si vous souhaitez utiliser le script à un autre moment pour mettre à jour le contenu de votre page, document.write est pratiquement inutile.

  2. Techniquement document.write, ne mettra à jour que les pages HTML et non XHTML / XML. IE semble être assez indulgent de ce fait, mais les autres navigateurs ne le seront pas.

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


9
IE pardonne car il ne prend pas en charge XHTML. Si / quand ils le font, document.write cessera probablement de fonctionner (uniquement en XHTML bien sûr).
Matthew Crumley

2
XHTML n'est pas pertinent sur le Web. Pages Même avec un doctype strict XHTML ne sont pas réellement traités comme XML à cet égard, les développeurs de navigateurs font les auteurs de pages non confiance que beaucoup.
RobG


3

Violation du navigateur

.writeest considéré comme une violation de navigateur car il empêche l'analyseur de restituer la page. L'analyseur reçoit le message que le document est en cours de modification; par conséquent, il est bloqué jusqu'à ce que JS ait terminé son processus. Ce n'est qu'à ce moment que l'analyseur reprendra.

Performance

La plus grande conséquence de l'utilisation d'une telle méthode est une baisse des performances. Le navigateur prendra plus de temps pour charger le contenu de la page. L'effet indésirable sur le temps de chargement dépend de ce qui est écrit dans le document. Vous ne verrez pas beaucoup de différence si vous ajoutez une <p>balise au DOM plutôt que de passer un tableau de 50 références à des bibliothèques JavaScript (quelque chose que j'ai vu dans le code de travail et qui a entraîné un délai de 11 secondes - de cela dépend aussi de votre matériel).

Dans l'ensemble, il vaut mieux éviter cette méthode si vous pouvez l'aider.

Pour plus d'informations, voir Intervention contre document.write ()


3

Sur la base d'une analyse effectuée par Google-Chrome Dev Tools ' Lighthouse Audit ,

Pour les utilisateurs sur des connexions lentes, les scripts externes injectés dynamiquement via document.write()peuvent retarder le chargement de la page de plusieurs dizaines de secondes.

entrez la description de l'image ici


2
  • Une raison simple pour laquelle document.writeune mauvaise pratique est que vous ne pouvez pas trouver un scénario où vous ne pouvez pas trouver une meilleure alternative.
  • Une autre raison est que vous traitez avec des chaînes plutôt qu'avec des objets (c'est très primitif).
  • Il ne s’ajoute qu’aux documents.
  • Il n'a rien de la beauté par exemple du modèle MVC (Model-View-Controller) .
  • Il est beaucoup plus puissant de présenter du contenu dynamique avec ajax + jQuery ou angularJS .

En ce qui concerne votre première puce, comment allez-vous résoudre ce que @sunwukung décrit dans sa réponse ci-dessus? Je suis d'accord que vous pourriez le résoudre avec des manipulations DOM, mais comme les manipulations DOM vont, il est difficile d'éviter FUOC parfois sans document.write.
bert bruynooghe

FUOC est-il un problème?
Anders Lindén

1

On peut penser à document.write () (et .innerHTML) comme évaluant une chaîne de code source. Cela peut être très pratique pour de nombreuses applications. Par exemple, si vous obtenez du code HTML sous forme de chaîne à partir d'une source, il est pratique de simplement «l'évaluer».

Dans le contexte de Lisp, la manipulation DOM serait comme manipuler une structure de liste, par exemple créer la liste (orange) en faisant:

(cons 'orange '())

Et document.write () serait comme évaluer une chaîne, par exemple créer une liste en évaluant une chaîne de code source comme ceci:

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

Lisp a également la capacité très utile de créer du code en utilisant la manipulation de liste (comme utiliser le "style DOM" pour créer un arbre d'analyse JS). Cela signifie que vous pouvez créer une structure de liste en utilisant le "style DOM", plutôt que le "style de chaîne", puis exécuter ce code, par exemple comme ceci:

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

Si vous implémentez des outils de codage, comme de simples éditeurs en direct, il est très pratique d'avoir la possibilité d'évaluer rapidement une chaîne, par exemple en utilisant document.write () ou .innerHTML. Lisp est idéal dans ce sens, mais vous pouvez faire des trucs très sympas aussi dans JS, et beaucoup de gens le font, comme http://jsbin.com/


1

Les inconvénients de document.write dépendent principalement de ces 3 facteurs:

a) Mise en œuvre

Le document.write () est principalement utilisé pour écrire du contenu à l'écran dès que ce contenu est nécessaire. Cela signifie que cela se produit n'importe où, soit dans un fichier JavaScript, soit à l'intérieur d'une balise de script dans un fichier HTML. Avec la balise de script placée n'importe où dans un tel fichier HTML, c'est une mauvaise idée d'avoir des instructions document.write () à l'intérieur de blocs de script qui sont entrelacées avec du HTML à l'intérieur d'une page Web.

b) Rendu

Un code bien conçu en général prendra tout contenu généré dynamiquement, stockez-le en mémoire, continuez à le manipuler pendant qu'il traverse le code avant qu'il ne soit finalement recraché à l'écran. Donc, pour réitérer le dernier point de la section précédente, le rendu du contenu sur place peut être rendu plus rapidement que tout autre contenu sur lequel on peut compter, mais il peut ne pas être disponible pour l'autre code qui à son tour nécessite que le contenu soit rendu pour traitement. Pour résoudre ce dilemme, nous devons nous débarrasser du document.write () et l'implémenter correctement.

c) Manipulation impossible

Une fois qu'il est écrit, c'est fini et fini. Nous ne pouvons pas revenir en arrière pour le manipuler sans puiser dans le DOM.


1

Je ne pense pas que l'utilisation de document.write soit une mauvaise pratique. En termes simples, c'est comme une haute tension pour les personnes inexpérimentées. Si vous l'utilisez mal, vous vous faites cuire. Il existe de nombreux développeurs qui ont utilisé cette méthode et d'autres méthodes dangereuses au moins une fois, et ils ne creusent jamais vraiment leurs échecs. Au lieu de cela, lorsque quelque chose ne va pas, ils se renflouent et utilisent quelque chose de plus sûr. Ce sont eux qui font de telles déclarations sur ce qui est considéré comme une "mauvaise pratique".

C'est comme formater un disque dur, lorsque vous devez supprimer seulement quelques fichiers, puis dire "formater le disque est une mauvaise pratique".


-3

Je pense que le plus gros problème est que tous les éléments écrits via document.write sont ajoutés à la fin des éléments de la page. C'est rarement l'effet souhaité avec les mises en page modernes et AJAX. (vous devez garder à l'esprit que les éléments du DOM sont temporels et que l'exécution du script peut affecter son comportement).

Il est préférable de définir un élément d'espace réservé sur la page, puis de manipuler son innerHTML.


15
Ce n'est pas vrai. document.write n'ajoute pas le contenu à la fin de la page comme s'il s'agissait d'une annexe. Ils sont écrits sur place.
Peter Bailey

1
@Peter Bailey, je sais que c'est un vieux fil de discussion, mais vraiment cela ne devrait pas être rétrogradé. qu'il soit ajouté ou non dépend du fait que document.write () s'exécute en ligne pendant le chargement de la page. S'il est appelé à partir d'une fonction après le chargement de la page, le premier document.write () remplacera le corps entier et les appels suivants y seront ajoutés.
Octopus

3
@Octopus Oui, mais c'est circonstanciel. Il s'ajoute dans ce scénario uniquement parce qu'il y a un nouveau document. Il n'est toujours pas exact de dire «document.write () ajoute». Oui, c'est une vieille réponse et un vieux downvote, mais je reste fidèle.
Peter Bailey

C'est bon. J'ai parlé de façon imprécise. Je l'aurais édité il y a longtemps, mais il y a une bien meilleure réponse ci-dessus. Je voudrais cependant souligner que «écrit sur place» est également imprécis.
BnWasteland
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.