chrome和firefox中document.write的行为不一致

时间:2015-03-24 17:17:26

标签: javascript google-chrome

问题

执行多个document.write时,我注意到他们没有立即修改DOM。第一个document.write立即执行,而其他人对DOM的影响仅在<script>块的末尾可见。在我测试的Chrome中,它给出了下面的结果。但是在Firefox中,结果与Chrome相同,如果我只是让这段代码运行但不同(见下文),当我一次单步执行代码时。有人可以解释这种行为吗?

代码

<script>  
    document.write("<script src='test.js'>" + "</" + "script>");  
    console.log(document.scripts.length);  
    document.write("<script src='test2.js'>" + "</" + "script>");  
    console.log(document.scripts.length);  
    document.write("<script src='test3.js'>" + "</" + "script>");  
    console.log(document.scripts.length);
</script>

Chrome(v.41)日志

2
2
2

Firefox(v.36)日志(当单步执行Dev Tools中的代码时)

2
3
4

更新

DOM中的原始脚本数为1(上面列出的内联脚本)。 Chrome在第一个document.write之后更新了DOM,但在此之后等待。那被认为是有缺陷的行为吗?

2 个答案:

答案 0 :(得分:0)

问题中的Chrome行为与4.01 specification's model:

完全匹配
  

18.2.4文件的动态修改

     

加载文档时执行的脚本可能能够动态修改文档的内容。这样做的能力取决于脚本语言本身(例如,某些供应商支持的HTML对象模型中的&#34; document.write&#34; 语句)。   文档的动态修改可以建模如下:

     

1。在文档加载时,将按顺序评估所有SCRIPT元素。

     

2。 评估生成SGML CDATA的给定SCRIPT元素中的所有脚本构造。他们的组合生成文本将插入到文档中以代替SCRIPT元素。

     

3. 生成的CDATA将重新评估

*(大胆的重点是我的)

Chrome和Firefox可能正在通过(2)&lt; =&gt;(3)在良好形成的未组合生成的文本上执行前瞻,但他们应该表现得好像他们没有根据规范模型评估它们。

因此, Chrome会报告文档中相同数量的脚本,直到父脚本终止,而不是&#34; buggy&#34; 。 (您应该假设您以这种方式添加的所有内容都将被添加/评估,就像它在页面中的下一个脚本元素之前一样,而不是更多。)

由于HTML5正在逐步部署,因此HTML 4.01行为应该是正确的并且是文档所期望的,并且它无法依赖HTML5中的任何说明,无论它是否指定HTML5 DOCTYPE 。因此,在保护4.01中定义的行为时,几乎没有理由查看HTML5规范。 对于4.01中存在的任何功能,每个文档必须与4.01兼容,直到有新的DOCTYPE指示不兼容,而不是请求新功能(如果可用)。

答案 1 :(得分:0)

我无法找到有关该文档的官方文档,但是进行了一些测试我发现浏览器会在脚本的源URL响应后将这些脚本附加到文档中(除了第一个)

&#13;
&#13;
document.write("<script src='a.js'>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script src='b.js'>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script src='c.js'>" + "</" + "script>");
console.log(document.scripts.length);

document.onreadystatechange = function() {
	if (document.readyState == "complete") {
		console.log('Complete: '+document.scripts.length+' scripts found')
	}
}
&#13;
&#13;
&#13;

在Chrome控制台中,您应该会看到类似这样的内容 enter image description here

但如果他们没有源

,它会立即加载脚本

&#13;
&#13;
document.write("<script>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script>" + "</" + "script>");
console.log(document.scripts.length);
&#13;
&#13;
&#13;

此外我还注意到,如果只有一个<script>已定义了源,则在采取响应之前,以下脚本(即使没有源代码)也不会附加到文档

&#13;
&#13;
document.write("<script>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script src='a.js'>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script>" + "</" + "script>");
console.log(document.scripts.length);
&#13;
&#13;
&#13;

然而,将async添加到<script>将解决问题

&#13;
&#13;
document.write("<script src='a.js' async>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script src='b.js' async>" + "</" + "script>");  
console.log(document.scripts.length);
document.write("<script src='c.js' async>" + "</" + "script>");
console.log(document.scripts.length);

document.onreadystatechange = function() {
	if (document.readyState == "complete") {
		console.log('Complete: '+document.scripts.length+' scripts found')
	}
}
&#13;
&#13;
&#13;