4

So, I was reading an article on MSDN here concerning the many ways one can display text to a webpage using JavaScript. However, I found the last example quite confusing as the behavior of the example as described in the article and exhibited in IE11 does not match the behavior shown in Chrome.

Here is the example:

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="[StackOverlow document.write() question]">
<script type="text/javascript">
    function ShowTime()
    {
        var dt = new Date();
        document.write(dt.toTimeString());
        // var elem = document.getElementById("divElem");
        // elem.textContent = dt.toTimeString();
        window.setTimeout("ShowTime();", 5000);
    }
</script>
</head>

<body>
<script type="text/javascript">
    ShowTime();
</script>
<div id="myDiv"></div>
</body>
</html>

The code is described as displaying the time only twice with a 5 second interval in between. This is correct for IE11. To be explicit, this is what is happening:

  1. The time is immediately displayed
  2. Wait 5 seconds
  3. The time displayed is updated to the current time

However, if I run the example in Chrome, it runs as follows:

  1. The time is immediately displayed
  2. Wait 5 seconds
  3. The time displayed is updated to the current time
  4. Wait 5 seconds
  5. A separate timestamp is displayed beside what is already displayed
  6. Repeat steps 4 and 5 indefinitely...

Can anyone please elaborate as to why the code behaves the way it does by explaining the mechanics behind using document.write() and setTimeout() for each browser?

Any help is much appreciated. Thank you in advance!

  • Why did you comment out the `.textContent` part? That appears to me to be the right code... – Jonathan Lam Jul 13 '16 at 02:43
  • I didn't comment it out. It came as a part of the example. I don't know if that part of the code has any influence on the behavior, so I left it in their to be true to the source I got it from. –  Jul 13 '16 at 02:46
  • You can not use document.write after the page loads – epascarello Jul 13 '16 at 02:54
  • Forget that `document.write` exists -- once a page load, it doesn't do what you think it does. – Jeremy J Starcher Jul 13 '16 at 02:57
  • Usually if you run `document.write()` *after* the page has finished loading it will overwrite the contents of the entire page due to an implicit `document.open()`, so it's almost never the correct function to use, especially not from a timeout. And I guess that explains the IE11 behaviour. But in Chrome, maybe because you're not doing anything else between timeouts Chrome considers the page still open for writing? – nnnnnn Jul 13 '16 at 02:57
  • 1
    http://stackoverflow.com/questions/802854/why-is-document-write-considered-a-bad-practice – epascarello Jul 13 '16 at 03:00

2 Answers2

0

First off, you should never use document.write(). Early on it was the only way to write stuff the the DOM but today it should only be used... well, really it should not be used. Ever. And I would be happy if they deprecated and removed it altogether.

Each element is added to the DOM and scripts are executed in the order it is received (top to bottom). So the script tag in the header is executed first. Since it only has a function in it, nothing get executed. It simply stores the ShowTime function in memory to be used at some other time.

It then continues loading the rest of the DOM until it reaches the second script tag. It executes it as well. That tag calls ShowTime so the pointer jumps into the ShowTime function and executes it from the top down (this is why I moved the second script after the myDiv div tag, executing it before that tag exists means it has not been added to the DOM yet and the document.getElementById would return a null value which means the elem.textContent = ... would halt with an error complaining that elem is not an object and does not contain a textContent property).

setTimeout delays the execution of a function ONE TIME. However, since the setTimeout is within the function it will essentially "infinite loop". Once the function is called once it will run and set the time into the div with ID "myDiv" then will call the setTimeout function to call itself again. So after 5 seconds it calls itself again then sets another timeout for another 5 seconds. Then executes itself again and again sets another timeout for 5 seconds... you see the pattern happening here. There should be no difference per browser. They should all handle this the same way.

So... using the commented code should work fine (and is the accepted way to write to a DOM element):

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="[StackOverlow document.write() question]">
<script type="text/javascript">
    function ShowTime()
    {
        var dt = new Date();
        var elem = document.getElementById("myDiv");
        elem.textContent = dt.toTimeString();
        window.setTimeout("ShowTime();", 5000);
    }
</script>
</head>

<body>
<div id="myDiv"></div>
<script type="text/javascript">
    ShowTime();
</script>
</body>
</html>

So back to document.write. Why does it behave differently in each browser? According to the standard, document.write() is supposed to write to a new document only. If the document already exists (e.g. the page you have the script in), it is supposed to execute a document.open() first which will clear all contents of the page and start a new, blank document. Why does Chrome not clear? I don't know. The developers may have not updated the function since it is not recommended that it be used anymore. I did a search and did not come up with anything as far as why the behavior of Chrome would be different. I tested it on a site and the site cleared for me, so you may be using an older version of Chrome that maybe has a bug? Unfortunately I can't offer a better explanation but definitely feel you should heed the warnings and avoid using document.write altogether.

Jim
  • 2,273
  • 1
  • 12
  • 21
  • Thank you for the very elaborate and detailed explanation. Yes, I realize that there are better ways to write to the DOM. I'm just trying to understand what makes the behavior for each browser act differently at such a rudimentary level like using `document.write`. However, I'm getting the strong impression from you and nearly everyone else that using `document.write` may have unpredictable consequences. I understand that now. Also, I updated Chrome, but nothing changed. Try creating your own web page and open it using Chrome. That's what I did before posting. –  Jul 14 '16 at 01:42
0

use document.open() and document.close()

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="[StackOverlow document.write() question]">
<script type="text/javascript">
    function ShowTime()
    {
        var dt = new Date();
        document.open();
        document.write(dt.toTimeString());
        document.close();
        // var elem = document.getElementById("divElem");
        // elem.textContent = dt.toTimeString();
        window.setTimeout(ShowTime, 5000);
    }
</script>
</head>

<body>
<script type="text/javascript">
    ShowTime();
</script>
<div id="myDiv"></div>
</body>
</html>
Community
  • 1
  • 1
  • Thank you for this! It definitely provides a clue as to what could be causing the difference between Chrome and IE11. I tried this using Chrome and apparently you don't need `document.open()` in order to produce the same result. –  Jul 14 '16 at 01:51