使用document.write下载和执行脚本的顺序

时间:2015-01-26 09:44:05

标签: javascript execution document.write

我有这段代码:

<script>
    document.write('<script src="1.js"><\/script>');
</script>
<script>
    document.write('<script src="2.js"><\/script>');
</script>
<script src="3.js"></script>

在网络控制台中,我可以看到3.js1.js之前已下载2.js。但是,执行顺序符合预期(1.js2.js3.js)。

据我所知document.write正在阻止,因此应在调用3.js后下载脚本document.write

为什么在使用3.js插入的脚本之前下载document.write

1 个答案:

答案 0 :(得分:1)

由于HTML parser blocks whilst parsing and executing JavaScript,保证了执行顺序。如果脚本的src网址尚未下载(请参见下文),则必须在解析脚本之前进行。这是个坏消息 - 这意味着HTML解析器无法继续阅读文档,因为它正在等待可能很慢的HTTP响应。

在您的示例中,HTML解析器必须等到第一个内联<script>执行后再转到下一个输入。

执行完毕后,下一个输入是它插入文档的<script src="1.js"... >。 HTML解析器阻塞,同时在移动到下一个内联脚本之前对其进行提取,解析和执行,依此类推。这导致执行顺序:

  1. <script>document.write('<script src="1.js"><\/script>');</script>
  2. <script src="1.js"></script>
  3. <script>document.write('<script src="2.js"><\/script>');</script>
  4. <script src="2.js"></script>
  5. <script src="3.js"></script>
  6. 但是,浏览器可以自由决定何时以及如何下载资产。这可以独立于脚本执行的顺序。

    现代浏览器常见pre-fetch assets以减少脚本下载时HTML解析器被阻止的时间。

    您首先看到3.js已下载,因为浏览器会在浏览器中扫描资产并立即开始下载脚本。一旦HTML解析器解析并执行了相应的内联1.js标记,它就只能开始下载2.jsscript

    这意味着在下载1.js2.js时,HTML解析器已被阻止。如果您的所有脚本都直接包含在3.js中,则浏览器可能会并行预取三个脚本,从而使页面加载效率更高。

    预取实现是特定于浏览器的,因此您可能会在其他浏览器中看到不同的结果。