HTML中多个<script>标签的含义

39

我读到过在HTML中多次实例化jQuery是不推荐的。这对我来说非常有道理,但是:

不是Javascript本身就是单线程的吗?除了jQuery之外,浏览器如何执行这些多个脚本标签?是并行执行还是一个接一个地执行?

谢谢,Philip


4
我曾经读到过在HTML中多次实例化jQuery并不推荐。您有相关链接吗? - Nabab
不好意思,也许我也有些错漏或遗漏了细节。实际上jQuery是无状态的,但插件可以(在某些情况下必须)被多次实例化。 - Philip
5个回答

48

简单回答:

在简单的情境下(标签是原始HTML文本的一部分),浏览器肯定是按顺序逐个执行它们。

详细讨论及相关注意事项:

JavaScript 不一定是单线程的(这取决于你使用的 JavaScript 引擎的实现,例如参见Web Workers)。

但是,各个<script>标签是按顺序执行的。

可参考《JavaScript权威指南》第12.3章"JavaScript程序的执行"。引用如下:

出现在 <script> 标签之间的 JavaScript 语句将按照出现的顺序进行执行;当文件包含多个脚本时,这些脚本的执行顺序就是它们出现的顺序。如果一个脚本调用了document.write()方法,那么该方法传递的任何文本都会被立即插入到结束 </script> 标签之后,并且在脚本运行完毕后由 HTML 解析器解析。从 src 属性引入的外部文件中的脚本也遵循相同的规则。


请注意,上述内容仅适用于标签中“直接执行”代码。但是,顺序可能会受到以下影响:
  • setTimeout() 调用(显然)

  • defer 属性

  • 动态附加 <script> 标签 - 请参见本答案的最后一节。


作为一个警告,请注意通过<script src="xxxx" />从外部加载的JavaScript代码仍将按顺序执行,但是,浏览器很可能会并行下载代码 - 这取决于浏览器的实现(但仍然按正确顺序调度已下载代码片段的执行)。
这个警告很重要,因为如果您想要一些奇怪的黑客,其中JavaScript源的URL实际上是CGI脚本,它做某些事情,并且您尝试依赖正确的下载顺序来处理脚本中的逻辑。
同样,它对您的浏览器JS引擎执行那些脚本片段的顺序没有影响。
然而,更为重要的警告是,如果您通过appendChild()调用动态地附加外部源的<script>标签,根据这篇SO帖子以及该帖子基于的MSDN博客,非IE浏览器不保证执行顺序!它将取决于哪个标签的代码先下载完成!

3
谢谢你提供这样详尽的答案! - Philip
3
顺便提一下,这似乎是IE领先于竞争对手的一个方面 ;) - Philip
@DVK:这是否意味着在<script type="text/javascript">中,如果我们包含了几个脚本,并且每个脚本都执行了AJAX和其他函数调用。第一个脚本会完成所有执行吗?然后它移动到下一个脚本?还是只是决定启动顺序而不是完成顺序? - NeverGiveUp161
@DVK:你能否提供一下你对这个问题的看法?http://stackoverflow.com/questions/42254196/disable-tabs-and-submit-button-on-form-until-all-the-script-executes - NeverGiveUp161

7

尽量减少实例化jQuery对象的调用,可以减少开销。但即使你在设计面向第二代硬件上运行的旧浏览器,也要谨慎微观优化。对应用程序进行分析,并修复实际上是瓶颈的部分。

至于浏览器处理多个脚本标签的方式,它因浏览器而异,因版本而异,有时甚至因操作系统而异。所有浏览器按文档顺序执行每个脚本标签:

<script src="scripts/some_script.js"></script> <!-- Executed 1st -->
<script src="scripts/some_other_script.js"></script> <!-- Executed 2nd -->
<script>
// Some JavaScript
</script> <!-- Executed 3rd -->
<script>
// Some More JavaScript
</script> <!-- Executed 4th -->

然而,其他行为没有定义并且存在差异。例如,在 Opera(至少在 Windows XP 上的 10.6 版本)中,每个脚本标签都在自己的上下文中运行 - 因此如果在第四个脚本块中引用了第三个脚本块的局部变量,则该变量将超出范围。

<script>
var i = 42;
</script>
<script>
alert(i);
// Alerts "undefined" in Opera, but 42 in Firefox.
</script>

2
我认为需要注意的是,如果我们谈论符合ECMA标准的浏览器,那么浏览器或操作系统之间没有区别——在ECMA实现中只有一个执行上下文。你提到的Opera版本可能不符合ECMA标准。 - Scott Marcus
你能在这里发表评论吗?http://stackoverflow.com/questions/42254196/disable-tabs-and-submit-button-on-form-until-all-the-script-executes - NeverGiveUp161

2

浏览器按顺序执行JavaScript代码(jQuery也是JavaScript,同样如此)。

至于在HTML中有多个


0

浏览器在处理过程中不是会将所有的JavaScript编译成一个“文件”吗?例如,如果您在多个文件中有多个$(document).ready()调用,当浏览器预处理页面时,它会将所有内容压缩以便执行,并按照它们被“看到”的顺序顺序运行。


我建议不要在$(document).ready(){});或建议使用的形式$(function(){});中放置多个事件处理程序,这将是一种不好的实践。努力只在页面上有一个事件处理程序。 - Mark Schultheiss

-3

是的,我们可以在 <body> 标签内编写任意数量的 <p> 标签。浏览器按顺序访问它们。

 <html>
   <body>

    <!-- here your code-->

      <script></script>
      <script></script>
      <script></script>
              .
              .
              .
      <script></script>

    </body>
</html>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接