Why Is Document.Write Considered a "Bad Practice"

Why is document.write considered a bad practice?

A few of the more serious problems:

  • document.write (henceforth DW) does not work in XHTML

  • DW does not directly modify the DOM, preventing further manipulation (trying to find evidence of this, but it's at best situational)

  • DW executed after the page has finished loading will overwrite the page, or write a new page, or not work

  • DW executes where encountered: it cannot inject at a given node point

  • DW is effectively writing serialised text which is not the way the DOM works conceptually, and is an easy way to create bugs (.innerHTML has the same problem)

Far better to use the safe and DOM friendly DOM manipulation methods

Is document.write actually deprecated?

No. It's just most often considered bad practice and almost as misused as eval.

Read: Why is document.write considered a 'bad practice'?

Quoting some important points from the linked question above:

  • document.write (henceforth DW) does not work in XHTML

  • DW executed after the page has finished loading will overwrite the page, or write a new page, or not work

  • DW executes where encountered: it cannot inject at a given node point

Also as @JaredFarrish stated, deprecated is mostly a state of mind. It's a relic that most likely will never go away otherwise it'd break many sites - even the Traditional Google Analytics code uses DW.

Obviously, functionality-wise it has been superseded long ago by proper DOM manipulation methods, and quoting the linked question above again: DW is effectively writing serialised text which is not the way the DOM works conceptually.


To counterbalance, here's a list of where DW may be considered appropriate:

  • There's nothing wrong with DW, per se - it won't destroy your page if you use it appropriately;
  • It allows for easily fallbacking an external script to a local copy such as when loading jQuery from a CDN fails:

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script>window.jQuery || document.write('<script src="js/libs/jquery-1.8.2.min.js">\x3C/script>');</script>
  • It's one of the easiest ways to insert external snippets in your page while keeping the code short (e.g. analytics). Note that systems such as Google Analytics now favor the asynchronous method - creating a script element through the document.createElement API, setting its properties and appending it to the DOM - rather than using its traditional document.write method.

tl;dr:

DW is easily misused, hence for real world use, prefer a proper DOM manipulation method whenever viable.

Why not document.write?

When used correctly, it's fine, but of very limited use.

You can't use it in XHTML, but I would recommend not using XHTML anyway unless you have a really, really good reason to.

The problem comes when you call document.write after the initial page load is complete. During page load is fine, but afterward, it causes an implicit document.open, which clears the document from the window and starts fresh.

Using document.write also means you can't demand-load your scripts or use the async or defer attributes on your script elements.

Finally, I usually recommend putting your JavaScript in a separate (single) JavaScript file at the very end of the document (just before the closing </body> tag). If you want to use document.write to output to the page, you'd have to include that script file higher up or use code directly within the HTML, neither both of which I recommend against.

So since it's of such limited use compared with other methods, it's best to get proficient with the other methods.

What damage is done by document.write()?

Use of document.write() will break a web page - destroying and overwriting the entire DOM - if it's called after the document has finished being parsed. This is considered a poor use of document.write() and is/was the reason for criticism of a lot of older scripts.

window.onload = function ()
{
document.write("Oops!");
}

Generally though, it's acceptable and rather widely used at parse-time to add something dynamically to the page in a synchronous manner:

<div>
<script type="text/javascript">
document.write("Well I'll be, your browser supports JavaScript!");
</script>
</div>

It's mostly used by ad publishing services for adding the advertisements to a page, some Google APIs also use it.

Is it considered bad practice to use document.on()?

I'd avoid it if possible. You have to realize that almost every event bubbles up to the top. Then jQuery has to query the target with your selector; probably a different one for each event bound this way. That can add up.

I have personally been confronted with legacy code that made heavy use of the now gone function .live(). As can be seen in this answer, that is equivalent to binding to document.

We ended up having sometimes multiple second latency on click events because of this. After fixing the unnecessary live() bindings because they were causing some obscure bugs, we ended up with massive usability improvements.

You also can't suppress events at that point because the default action has possibly already taken place. You should bind more specifically if you can. And in all likelihood, you can.

Is document write the preferred way to write html to a third party site for corporate branding?

You don't need to document.write(); in order to inject code into the head. If they embed your remote JavaScript file into their page, anywhere, you should be able to just append a script/style elements to the head.

 var myScript = document.createElement('script');
myScript.setAttribute('src', '...');
myScript.setAttribute('type', 'text/javascript');
document.getElementsByTagName('head')[0].appendChild( myScript );

If you look at the Google Analytics embed code, you'll see some similarities. It's short enough that you should be able to figure out what is going on:

<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', '...', 'auto');
ga('send', 'pageview');

</script>

using document.write in remotely loaded javascript to write out content - why a bad idea?

To be honest, I don't really see a problem. Yes, document.write is very old-school, but it is simple and universally supported; you can depend on it working the same in every browser.

For your application (writing out a HTML table with some data), I don't think a more complex solution is necessary if you're willing to assume a few small risks. Dealing with DOM mutation that works correctly across browsers is not an easy thing to get right if you're not using jQuery (et al).

The risks of document.write:

  • Your script must be loaded synchronously. This means a normal inline script tag (like you're already using). However, if someone gets clever and adds the async or defer attributes to your script tag (or does something fancy like appending a dynamically created script element to the head), your script will be loaded asynchronously.

    This means that when your script eventually loads and calls write, the main document may have already finished loading and the document is "closed". Calling write on a closed document implicitly calls open, which completely clears the DOM – it's esentially the same as wiping the page clean and starting from scratch. You don't want that.

  • Because your script is loaded synchronously, you put third-party pages at the mercy of your server. If your server goes down or gets overloaded and responds slowly, every page that contain your script tag cannot finish loading until your server does respond or the browser times out the request.

    The people who put your widget on their website will not be happy.

If you're confident in your uptime, then there's really no reason to change what you're doing.

The alternative is to load your script asynchronously and insert your table into the correct spot in the DOM. This means third parties would have to both insert a script snippet (either <script async src="..."> or use the dynamic script tag insertion trick. They would also need to carve out a special <div id="tablegoeshere"> for you to put your table into.

Avoid document.write()

Recommended: Element.append()

You can create an element using document.createElement().
That element can then be appended to document.body.