我有这段代码:
<script>
document.write('<script src="1.js"><\/script>');
</script>
<script>
document.write('<script src="2.js"><\/script>');
</script>
<script src="3.js"></script>
在网络控制台中,我可以看到3.js
和1.js
之前已下载2.js
。但是,执行顺序符合预期(1.js
,2.js
,3.js
)。
据我所知document.write
正在阻止,因此应在调用3.js
后下载脚本document.write
。
为什么在使用3.js
插入的脚本之前下载document.write
?
答案 0 :(得分:1)
由于HTML parser blocks whilst parsing and executing JavaScript,保证了执行顺序。如果脚本的src
网址尚未下载(请参见下文),则必须在解析脚本之前进行。这是个坏消息 - 这意味着HTML解析器无法继续阅读文档,因为它正在等待可能很慢的HTTP响应。
在您的示例中,HTML解析器必须等到第一个内联<script>
执行后再转到下一个输入。
执行完毕后,下一个输入是它插入文档的<script src="1.js"... >
。 HTML解析器阻塞,同时在移动到下一个内联脚本之前对其进行提取,解析和执行,依此类推。这导致执行顺序:
<script>document.write('<script src="1.js"><\/script>');</script>
<script src="1.js"></script>
<script>document.write('<script src="2.js"><\/script>');</script>
<script src="2.js"></script>
<script src="3.js"></script>
但是,浏览器可以自由决定何时以及如何下载资产。这可以独立于脚本执行的顺序。
现代浏览器常见pre-fetch assets以减少脚本下载时HTML解析器被阻止的时间。
您首先看到3.js
已下载,因为浏览器会在浏览器中扫描资产并立即开始下载脚本。一旦HTML解析器解析并执行了相应的内联1.js
标记,它就只能开始下载2.js
和script
。
这意味着在下载1.js
和2.js
时,HTML解析器已被阻止。如果您的所有脚本都直接包含在3.js
中,则浏览器可能会并行预取三个脚本,从而使页面加载效率更高。
预取实现是特定于浏览器的,因此您可能会在其他浏览器中看到不同的结果。