【问题标题】:Why does this setInterval/document.write code work on Chrome but not on Firefox?为什么这个 setInterval/document.write 代码可以在 Chrome 上运行,但不能在 Firefox 上运行?
【发布时间】:2016-01-20 15:05:28
【问题描述】:

这是一个在浏览器窗口中打印数字一到十的简单程序。

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);

这适用于 Chrome(数字 1 到 10 出现,它们之间有短暂的延迟),但不适用于 Firefox(仅出现 1,没有错误)。为什么?

我知道我可以使用console.log,但这不是重点。为什么 document.write 在 Chrome 和 Firefox 之间的工作方式不同?

【问题讨论】:

  • 加载页面后,文档将关闭。你不能再在上面使用document.write,因为它会创建一个新文档,有效地覆盖你在浏览器中的页面。使用更明智的方法,例如 DOM 方法或(至少出于测试目的)console.log
  • @NiettheDarkAbsol:对。所以问题是,为什么 Chrome 不这样做呢? jsbin.com/lucajut - 在 Chrome 上,它显示从 1 到 10 的数字,但在 Firefox 上它停在 1。
  • @AdamKonieska 有趣的是如何更改使它不起作用的代码位,突然使它起作用:p
  • 我对这方面的多个方面感到惊讶。 Chrome 执行 1-10,Firefox 停止在 1 而不是显示 1,然后替换 2,然后是 3,直到最后只显示 10。
  • 对我来说,Opera 和 Safari 遵循 Chrome 的行为,而 IE 遵循 Firefox 的行为。情节变厚了。

标签: javascript google-chrome firefox


【解决方案1】:

这是 Chrome WebKit 中的一个错误;根据Kaiido,它也发生在 Safari 上。

在页面的主要解析完成后调用document.write 涉及对document.open 的隐式调用。 According to the specification,调用document.open 应该销毁文档,删除所有事件处理程序,并丢弃所有任务。这意味着 Firefox 的操作是正确的,因为它在空白文档中显示 1。因为setInterval安排的任务已经被丢弃了,所以没有继续下去。

正如您所指出的,有时 Firefox 微调器会继续运行,就像它在期待其他事情发生一样。我喜欢Adam Konieska's theory 的原因:当我们执行document.write(1) 时,我们隐式执行了document.open,它正在等待document.close。事实上,如果我们在您的代码中添加 document.close 来测试它,微调器就不会留下来:

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);

【讨论】:

  • 但是为什么选项卡上的 Firefox 加载器图标总是转来转去,好像在寻找什么?
  • @BA:对我来说,它是否这样做是不可靠的。如果这是一个 Firefox 错误,我不会感到惊讶。将document.write 放入setInterval 是一件相当不寻常的事情,可能没有经过充分测试。
  • @BA 可能是因为缺少document.close()
  • @AdamKonieska:是的,你是对的,刚刚通过添加 document.close 进行测试。
  • 我可以在 safari 上确认相同的行为
【解决方案2】:

除了 T.J.关于 webkit 错误的杂烩,请考虑这两个脚本,以及为什么您的代码具体不能像您预期的那样工作。

脚本 1

<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>

脚本 2

<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>

 

结果

脚本 1

首先,setInterval() 在页面关闭后再次触发。您将看到指示页面已完全执行的警报消息,并且该文档已关闭以供写入。 发生这种情况后,您将看到document.write 被第一个间隔触发。这将卸载以前关闭的旧文档,并仅将 1&lt;br /&gt; 添加到页面。

由于旧文档已被卸载,现有的 javascript 已经消失,除了第一次迭代之外没有其他内容可以执行。

脚本 2

在第二个脚本中,document.write 在当前文档仍处于打开状态时多次执行。由于document.write 函数在文档自然关闭之前执行,因此文档的原始内容永远不会被覆盖。

 

结论

直接与 DOM 元素交互比使用document.write 更好。

这里有一些更好的阅读:https://pigeoto.wordpress.com/2011/01/19/why-doesnt-document-write-work-with-setinterval/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多