通过具有异步属性的 HTML5 脚本标记的 Javascript 执行顺序

Posted

技术标签:

【中文标题】通过具有异步属性的 HTML5 脚本标记的 Javascript 执行顺序【英文标题】:Javascript execution order via HTML5 script tag with async attribute 【发布时间】:2013-03-06 09:43:14 【问题描述】:

阿罗哈。我一直在编写一个脚本,虽然我了解问题的每个组成部分的文档(并且查看了关于 SO 的许多其他问题),但我在实践中不了解这种特定行为。请注意,以下代码是隔离特定问题的缩写子集。这里是async.html

<!doctype html>
<html><head><script type="text/javascript" src="asyncTest.js" async="true"></script></head>
<body><ul id="menu"><li>one</li><li>two</li><li>three</li></ul></body></html>

这里是asyncTest.js

var _site = function() 
  var load = function() 
    var menuCategory = document.getElementById('menu').getElementsByTagName('li');
    for(var i=0; i<menuCategory.length; i++)  alert(i+'['+menuCategory[i]+']'); 
  ;

  return  load:load ;
();
window.addEventListener('load',_site.load(),false);

问题是如果没有&lt;script&gt; 标记中的async 属性,此代码无法将&lt;li&gt; 元素正确存储到menuCategory 中,就好像它在加载DOM 之前运行一样(即使我认为它应该在整个window“对象”加载后触发)。我觉得这很奇怪,因为我使用addEventListener() 仅在整个加载后才尝试运行它(并且它似乎在 Chromium、FF 和 Opera 中的适当时间运行——至少看起来是“适当的时间”)。如果有的话,我认为相反的情况会导致这种行为。

有人能解释一下吗,最好用老爱因斯坦“像你向六岁的孩子解释一样解释”?我显然在阅读中遗漏了一些东西。谢谢!

【问题讨论】:

请注意_site.load() 会立即调用_site.load 并将结果传递给window.onload。那是你要的吗?传递稍后调用的函数引用更为常见:window.addEventListener('load',_site.load,false);(注意缺少括号)。 这显然不是我们想要的。我正要写这个作为答案...... 是的,这正是问题所在。你能把这个写下来让我接受它作为答案吗? 【参考方案1】:

正如 RobG 在 cmets 中提到的,这里的问题是使用 _site.load()(在调用后带有括号)导致函数被执行,然后分配给 onload 事件。将此行为纠正为所需功能的方法是在不带括号的情况下调用它:_site.load(或_site().load)。

【讨论】:

以上是关于通过具有异步属性的 HTML5 脚本标记的 Javascript 执行顺序的主要内容,如果未能解决你的问题,请参考以下文章

js异步加载的5种方式

总结前端开发模式和规范 2HTML5中script的async属性异步加载JS

使用async属性异步加载执行JavaScript

使用async属性异步加载执行JavaScript

原生 JS 中 延迟脚本和异步脚本

HTML5 脚本标签,延迟等待任何以前的异步脚本