Here is a simple program that prints numbers one to ten on the browser window.
var t = 1; var a = function timer() { if (t < 11) { document.write(t + "<br/>"); t = t + 1; } else { clearInterval(handle); } } var handle = setInterval(a, 100);
This works on Chrome (the numbers 1 to 10 appear with a brief delay between them) but doesn't work on Firefox (just 1 appears, and no errors). Why?
I understand I could use console.log
, but that's not the point. Why is document.write
working differently between Chrome and Firefox?
It's a bug in Chrome WebKit; according to Kaiido , it also happens on Safari.
Calling document.write
after the main parsing of the page is complete involves an implicit call to document.open
. According to the specification , calling document.open
should destroy the document, remove all event handlers, and discard all tasks. That means what Firefox is doing is correct, because it shows 1 in a blank document. It doesn't keep going because the task scheduled by the setInterval
has been discarded.
As you've noted, sometimes the Firefox spinner keeps going, like it's expecting something else to happen. I like Adam Konieska's theory about why that is: When we did the document.write(1)
, we implicitly did a document.open
, and it's waiting for a document.close
. And in fact, if we add a document.close
to your code to test that, the spinner doesn't stick around:
var t = 1; var a = function timer() { if (t < 11) { document.write(t + "<br/>"); t = t + 1; document.close(); // Just to test Firefox's spinner } else { clearInterval(handle); } } var handle = setInterval(a, 100);
In addition to the points by TJ Chowder about the webkit bug, consider these two scripts and why your code specifically doesn't work like you may have expected.
<html>
<head>
<title>foo</title>
<script>
t = 1;
var a = function timer() {
if (t < 11) {
document.write(t + "<br/>");
t = t + 1;
}
}
setInterval(a, 100);
</script>
</head>
<body>
<script>
alert('page fully loaded')
</script>
</body>
</html>
<html>
<head>
<title>foo</title>
<script>
for(var i = 1; i < 11; i++) {
document.write(i + "<br />");
}
</script>
</head>
<body>
<script>
alert('page fully loaded')
</script>
</body>
</html>
In the first, setInterval()
is triggering again after the page is closed. You'll see the alert message indicating the page had executed fully, and the document is closed for writing. After that happens, you will see the document.write
being triggered by the first interval. This unloads the old, previously closed document, and adds only 1<br />
to the page.
Since the old document has been unloaded, the existing javascript is gone and there is nothing else to execute beyond the first iteration.
In the second script, document.write
is executed multiple times while the current document is still open. Since the document.write
functions are executed before the document is closed naturally, the original contents of the document are never overwritten.
Its better to interact with DOM elements directly than to use document.write
.
There is some more good reading on it here: https://pigeoto.wordpress.com/2011/01/19/why-doesnt-document-write-work-with-setinterval/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.