document.writeが「悪い習慣」と見なされるのはなぜですか?


363

document.writeは悪い習慣と見なされていることを知っています。また、サードパーティベンダーに提出する理由のリストdocument.writeを、分析コードの実装で使用してはいけない理由についてまとめたいと思っています。

document.write以下に、主張する理由を悪い習慣として記載してください。

回答:


243

より深刻な問題のいくつか:

  • document.write(以降DW)がXHTMLで機能しない

  • DWはDOMを直接変更せず、それ以上の操作を防止 します(これの証拠を見つけようとしますが、状況に応じて)

  • ページの読み込みが完了した後に実行されたDWは、ページを上書きするか、新しいページを書き込むか、機能しません

  • DWは遭遇した場所で実行されます:指定されたノードポイントで注入できません

  • DWは、DOMが概念的に機能する方法ではなく、バグを作成する簡単な方法であるシリアル化されたテキストを効果的に書き込んでいます(.innerHTMLにも同じ問題があります)

安全でDOMフレンドリーなDOM操作メソッドを使用する方がはるかに良い


39
-1、DOMを完全に変更します。それ以外はすべて問題ありません。私はあなたを害から守ることができる構造と方法に頼る衝動を理解していますが、これは赤ちゃんを風呂の水で捨てる場合かもしれません。
cgp 2009

7
FireBugはDOMの真の表現ではありません。これは、HTMLをDOMに解析するMozillaの試みです。Firebug DOMビューでは、完全に壊れたHTMLを適切に表示できます。
FlySwat 2009

8
DOMは、ページのレンダリングに使用されるデータ構造であり、ユーザーがページに表示するもののアルファとオメガです。HTML!= DOMは正しいですが、DOMがDWによって変更されているかどうかの問題には重要ではありません。DWがDOMを変更しなかった場合、画面は表示されません。これはすべてのブラウザーに当てはまり、ページのレンダリングにDOMが使用されている限り常にそうなります。
cgp 2009

8
「DWは遭遇した場所で実行されます」 -常に不利なわけではありません。実際、スクリプト要素を追加するなど、特定の事柄の利点と見なすことができます(実際には、DWを使用する唯一のことについて、そして私は2度考えます)。 。
nnnnnn

7
@RicardoRivaldoはい、document.writeドキュメントの読み込みが完了した後に呼び出された場合、そうです
イズカタ2013

124

実際にはdocument.write、それ自体には何の問題もありません。問題は、悪用しやすいことです。ひどく、さえ。

ベンダーが分析コード(Google Analyticsなど)を提供するという点では、実際にそのようなスニペットを配布するのが最も簡単な方法です。

  1. スクリプトを小さく保ちます
  2. すでに確立されているonloadイベントをオーバーライドしたり、onloadイベントを安全に追加するために必要な抽象化を含めたりする必要はありません。
  3. 非常に互換性があります

ドキュメントが読み込まれた後で使用しない限り、私の考えdocument.writeは本質的に悪ではありません。


3
document.writeは、HTMLパーサーに対して非常に恐ろしいことを行い、単純な場合にのみ「非常に互換性があります」。
olliej 2009

27
分析タグの挿入が好きですか?つまり、結局のところ、元の質問の一部です。そして、非常に互換性があるということは、document.writeメソッドに対するブラウザの直接サポートのみを意味します。
Peter Bailey、

Chrome / IE / Safari / Opera / FireFoxの最新バージョンで動作するものはすべて互換性があると見なされます。
Pacerier 2014年

2
onloadイベントをオーバーライドしますか?そして何のaddEventListenerためですか?
m93a 2015

Chromeはdocument.write、特定の条件が満たされたときにスクリプトを挿入する呼び出しを実行しません。
Flimm 2017

44

のもう1つの正当な使用法はdocument.write、HTML5ボイラープレート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>

json2.js JSON解析/文字列化ポリフィルを使用するための同じ手法も見ました(IE7以下で必要)。

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

11
ここでの使用は悪くありませんが、DOM操作関数を使用する方が「優れています」-GoogleでもGoogle Analyticsで使用できます。スニペットはこちらです。
BMiner 2013年

8
@BMiner scriptDOM操作を介して要素を挿入する場合、同期的に読み込まれますか?そうでなければ、それは交換ではありません。
John Dvorak

2
@JanDvorak-良い点。DOM操作を使用する場合、ブラウザは通常、スクリプトを非同期的にロードします。あなたは使用することができonload、非同期ロードされたスクリプトが使用可能であるかを決定するためにDOMイベントを。
BMiner 2013

1
@JanDvorak 外部でない場合(同期していない場合src)は、同期して読み込まれます。それ以外の場合は、非同期で「できるだけ早く」実行されます。
Oriol

1
ユーザーが2G接続を使用している場合、Chromeは意図的にタグdocument.writeを挿入する呼び出しの実行を拒否するため、これは依然として<script>失敗する可能性があります。developer.google.com/web/updates/2016/08/…を
Flimm

42

それはあなたのページをブロックすることができます

document.writeページの読み込み中にのみ機能します。ページの読み込みが完了した後に呼び出すと、ページ全体が上書きされます。

これは事実上、インラインスクリプトブロックから呼び出す必要があることを意味します。これにより、ブラウザーが後続のページの一部を処理できなくなります。スクリプトと画像は、書き込みブロックが完了するまでダウンロードされません。


31

プロ:

  • これは、外部(ホスト/ドメインへの)スクリプトからインラインコンテンツを埋め込む最も簡単な方法です。
  • フレーム/ iframe内のコンテンツ全体を上書きできます。より最近のAjax手法が広く利用できるようになるまで(1998-2002)、私はこの手法をメニュー/ナビゲーションの一部によく使用していました。

短所:

  • このスクリプトは、上記の外部スクリプトが読み込まれるまで一時停止するようにレンダリングエンジンをシリアル化します。これは、内部スクリプトよりもはるかに時間がかかる可能性があります。
  • 通常は、スクリプトがコンテンツ内に配置されるように使用されます。これは、不正な形式と見なされます。

3
それ以上の短所があります。たとえば、Google Chromeは特定の状況下でタグdocument.writeを作成することを拒否します<script>developers.google.com/web/updates/2016/08/...
Flimm

@Flimm注目に値します。あなたのコメントは私の回答から8年以上経過していますが、これはほぼ3年後のことです。ええ、他にも短所があります...そして、document.write自体が消えないのであれば、私は驚かれるでしょう。
Tracker1

10

ここに私の2ペンスの価値document.writeがあります。一般的に、重労働には使用しないでください。

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

私は最近、AJAXスライダーギャラリーを作成しようとしていることを発見しました。2つのネストされたdivを作成し、width/ heightおよびoverflow: hidden外部に適用しました<div> JS。これは、ブラウザでJSが無効になっている場合、divがフロートしてギャラリー内の画像に対応するようにするためです-いくつかの素晴らしい優雅な低下。

上記の記事と同様に、CSSのこのJSハイジャックは、ページが読み込まれるまで作動せず、divが読み込まれると瞬間的にフラッシュしました。そのため、ページが読み込まれるときに、CSSルールを記述するか、シートを含める必要がありました。

明らかに、これはXHTMLでは機能しませんが、XHTMLは死んだアヒルのように見える(そしてIEではタグスープとしてレンダリングされる)ため、DOCTYPEの選択を再評価する価値があるかもしれません...


7

それが最も明白な理由であるページ上のコンテンツを上書きしますが、私はそれを「悪い」とは言いません。

JavaScriptを使用してドキュメント全体を作成する場合を除き、これはあまり役に立ちません。その場合、document.writeで開始できます。

それでも、document.writeを使用するときにDOMを実際に利用しているわけではありません。テキストのblobをドキュメントにダンプしているだけなので、形式が悪いと思います。


2
1つの明確化:document.writeはページにコンテンツを挿入し、上書きしません。
Peter Dolberg、2009

5
@Peter、ドキュメントが読み込まれた後に呼び出すと、コンテンツが上書きされます。それがaleembの意味だと思います。
マシュークラムリー

2
代わりに、単に次のようなことをするのではなく、コードで個々のDOMノードを手動で構築するように提案していdiv.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";ますか?それは多くの不必要で読みにくいコードを生成するようです。これは、John Resigや他のJS開発者が主張するアプローチとは正反対です。
Lèseはmajesté

7

(XHTMLページのような)XMLレンダリングを使用してページを分割します。

最適:一部のブラウザはHTMLレンダリングに戻り、すべてが正常に動作します。

可能性:一部のブラウザーは、XMLレンダリングモードでdocument.write()関数を無効にします。

最悪:一部のブラウザでは、document.write()関数を使用するたびにXMLエラーが発生します。


6

私の頭の上から:

  1. document.writeページ読み込みまたは本文読み込みで使用する必要があります。したがって、スクリプトを他の時間に使用してページコンテンツを更新する場合、document.writeはほとんど役に立ちません。

  2. 技術的にdocument.writeはHTMLページのみを更新し、XHTML / XMLは更新しません。IEはこの事実をかなり許容しているようですが、他のブラウザはそうではありません。

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


9
IEはXHTMLをサポートしていないため、寛容です。もしそうである場合、その場合、document.writeはおそらく動作を停止します(もちろんXHTMLでのみ)。
Matthew Crumley、

2
XHTMLはWebでは無関係です。厳密なXHTML Doctypeを持つページでさえ、実際にはXMLとして扱われませんが、ブラウザ開発者はページ作成者それほど信頼していません。
RobG、2015年

4

document.write場合によっては、Chromeがスクリプトを挿入することをブロックすることがあります。これが発生すると、コンソールに次の警告が表示されます。

パーサーをブロックするクロスオリジンスクリプト...は、document.writeを介して呼び出されます。デバイスのネットワーク接続が不十分な場合、これはブラウザによってブロックされる可能性があります。

参照:


3

ブラウザ違反

.writeパーサーがページのレンダリングを停止するため、ブラウザ違反と見なされます。パーサーは、ドキュメントが変更されているというメッセージを受け取ります。したがって、JSがプロセスを完了するまでブロックされます。この時点でのみ、パーサーが再開されます。

パフォーマンス

このような方法を採用する最大の結果は、パフォーマンスの低下です。ブラウザがページコンテンツをロードするのに時間がかかります。ロード時間への悪影響は、ドキュメントに何が書き込まれているかによって異なります。あなたが追加している場合、あなたは違いの多くを見ることはありません<p>JavaScriptライブラリへの50の参照の配列を渡すのとは対照的に、DOMにタグを(私が作業コードで確認した結果、11秒の遅延が発生しました)もちろん、これはハードウェアにも依存します)。

全体として、もしあなたがそれを助けることができるなら、この方法を回避するのが最善です。

詳細については、document.write()に対する介入を参照してください。


3

Google-Chrome Dev ToolsのLighthouse Auditによる分析に基づいて、

接続が遅いユーザーの場合、動的に挿入される外部スクリプトdocument.write()により、ページの読み込みが数十秒遅れることがあります。

ここに画像の説明を入力してください


2
  • document.write悪い習慣である単純な理由は、より良い代替案を見つけることができないシナリオを考え出すことができないことです。
  • もう1つの理由は、オブジェクトではなく文字列を扱っているためです(非常に原始的です)。
  • 文書に追加するだけです。
  • たとえば、MVC(Model-View-Controller)パターンの美しさは何もありません。
  • 動的コンテンツをajax + jQueryまたはangularJSで表示する方がはるかに強力です

最初の弾丸については、@ sunwukungが上記の彼の答えで説明していることをどのように解決しますか?私はあなた DOM操作でそれを解決できることに同意しますが、DOM操作が進むにつれ、FUOCを使わずにFUOCを回避することは困難document.writeです。
bert bruynooghe

FUOCはもう問題ですか?
アンデルスリンデン

1

document.write()(および.innerHTML)は、ソースコード文字列を評価するものと考えることができます。これは、多くのアプリケーションで非常に便利です。たとえば、あるソースからHTMLコードを文字列として取得する場合、それを「評価」するだけで便利です。

Lispのコンテキストでは、DOM操作はリスト構造の操作に似ています。たとえば、次のようにしてリスト(オレンジ)を作成します。

(cons 'orange '())

また、document.write()は文字列を評価するようなものです。たとえば、次のようなソースコード文字列を評価してリストを作成します。

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

Lispには、リスト操作を使用してコードを作成する(「DOMスタイル」を使用してJS解析ツリーを作成するなど)非常に便利な機能もあります。つまり、「文字列スタイル」ではなく「DOMスタイル」を使用してリスト構造を構築し、そのコードを実行できます。たとえば、次のようにします。

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

シンプルなライブエディターなどのコーディングツールを実装する場合、たとえばdocument.write()や.innerHTMLを使用して、文字列をすばやく評価する機能があると非常に便利です。Lispはこの意味で理想的ですが、JSでも非常に優れた機能を実行でき、多くの人々がhttp://jsbin.com/のようにそれを実行しています。


1

document.writeの欠点は、主に次の3つの要因に依存します。

a)実装

document.write()は、コンテンツが必要になったときに画面にコンテンツを書き込むために主に使用されます。つまり、JavaScriptファイル内、またはHTMLファイル内のスクリプトタグ内のどこでも発生します。このようなHTMLファイル内のどこかにスクリプトタグが配置されているため、Webページ内のHTMLと絡み合うスクリプトブロック内にdocument.write()ステートメントを含めることはお勧めできません。

b)レンダリング

適切に設計されたコードは一般に、動的に生成されたコンテンツを取得してメモリに格納し、最終的に画面に吐き出される前にコードを通過しながら操作を続けます。したがって、前のセクションの最後のポイントを繰り返すと、コンテンツをインプレースでレンダリングすると、依存する可能性のある他のコンテンツよりも速くレンダリングされる可能性がありますが、処理のためにコンテンツをレンダリングする必要がある他のコードでは利用できない場合があります。このジレンマを解決するには、document.write()を削除して、正しい方法で実装する必要があります。

c)不可能な操作

いったん書かれると、それで終わりです。DOMを利用しないと操作に戻ることはできません。


1

document.writeの使用は悪い習慣だとはまったく思いません。簡単に言えば、それは経験の浅い人にとっては高電圧のようなものです。使い方を間違えると炊き上がります。この方法や他の危険な方法を少なくとも一度は使用したことがある開発者は多く、実際に失敗を掘り下げることはありません。代わりに、何かがうまくいかない場合、彼らは救済し、より安全なものを使用します。それらは「悪い習慣」と見なされるものについてそのような発言をする人です。

それは、ハードドライブをフォーマットするようなもので、ほんの数個のファイルを削除する必要があるときに、「ドライブのフォーマットは悪い習慣です」と言います。


-3

最大の問題は、document.writeで記述された要素がページの要素の最後に追加されることだと思います。最新のページレイアウトとAJAXでこれが望ましい効果になることはめったにありません。(DOMの要素は一時的なものであり、スクリプトを実行するとその動作に影響を与える可能性があることに注意してください)。

ページにプレースホルダー要素を設定してから、innerHTMLを操作する方がはるかに優れています。


15
本当じゃない。document.writeは、追加のようにページの最後にコンテンツを追加しません。彼らはその場で書かれています。
Peter Bailey、

1
@ピーターベイリー、私はこれが古いスレッドであることを知っていますが、実際にはこれは反対投票すべきではありません。追加するかどうかは、ページの読み込み中にdocument.write()がインラインで実行されるかどうかによって異なります。ページが読み込まれた後に関数から呼び出された場合、最初のdocument.write()が本文全体を置き換え、後続の呼び出しがそれに追加されます。
タコ

3
@タコはい、しかしそれは状況によるものです。そのシナリオでは、新しいドキュメントがあるという理由だけで追加されます。「document.write()が追加する」と言うのはまだ正確ではありません。はい、それは古い答えと古い反対投票ですが、私はまだそれを支持しています。
Peter Bailey

大丈夫だよ。私は不正確に話しました。私はずっと前にそれを編集したでしょうが、上記のはるかに良い答えがあります。「適所に書かれた」も同様に不正確であることを指摘しておきます。
BnWasteland 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.