pim*_*vdb 201 html javascript deferred-execution
我有一些<script>元素,其中一些元素依赖于其他<script>元素中的代码.我看到这个defer属性可以在这里派上用场,因为它允许在执行时推迟代码块.
为了测试它我在Chrome上执行了这个:http://jsfiddle.net/xXZMN/.
<script defer="defer">alert(2);</script>
<script>alert(1)</script>
<script defer="defer">alert(3);</script>
Run Code Online (Sandbox Code Playgroud)
但是,它提醒2 - 1 - 3.为什么不提醒1 - 2 - 3?
Alo*_*hci 162
来自HTML5规范的几个片段:http://w3c.github.io/html/semantics-scripting.html#element-attrdef-script-async
如果src属性不存在,则不能指定defer和async属性.
使用这些属性[async和defer]可以选择三种可能的模式.如果存在async属性,则脚本一旦可用就会异步执行.如果async属性不存在但是存在defer属性,则在页面完成解析时执行脚本.如果两个属性都不存在,则在用户代理继续解析页面之前立即获取并执行脚本.
出于大多数历史原因,这些属性的确切处理细节有些不平凡,涉及HTML的许多方面.因此,实施要求必须分散在整个说明书中.下面的算法(在本节中)描述了这个处理的核心,但是这些算法引用并引用HTML中的脚本开始和结束标记的解析规则,外部内容和XML,document.write的规则. ()方法,脚本处理等
如果元素具有src属性,并且元素具有defer属性,并且该元素已标记为"parser-inserted",并且该元素没有async属性:
必须将该元素添加到脚本列表的末尾,该脚本将在文档完成与创建该元素的解析器的Document相关联的解析时执行.
Chr*_*ini 155
真正的答案是:因为你不能相信推迟.
在概念上,延迟和异步的区别如下:
async允许脚本在后台下载而不会阻塞.然后,在完成下载的那一刻,渲染被阻止并且该脚本执行.脚本执行后渲染恢复.
defer做同样的事情,除了声称保证脚本按照它们在页面上指定的顺序执行,并且它们将在文档完成解析后执行.因此,某些脚本可能会完成下载,然后等待稍后下载但出现在它们之前的脚本.
不幸的是,由于什么是真正的标准猫斗争,推迟的定义根据规格变化规格,即使在最近的规格中也没有提供有用的保证.作为这里的答案和此问题的演示,浏览器实现的推迟不同:
defer脚本无序运行的错误.DOMContentLoaded在defer脚本加载之前将事件延迟,有些则不会.defer于<script>与内嵌代码,并没有元素src属性,有些忽略它.幸运的是,规范至少指定了异步覆盖延迟.因此,您可以将所有脚本视为异步,并获得大量的浏览器支持,如下所示:
<script defer async src="..."></script>
Run Code Online (Sandbox Code Playgroud)
全球98%的浏览器和美国的99%将使用这种方法避免阻塞.
(如果您需要等到文档完成解析,请听事件DOMContentLoaded事件或使用jQuery的方便.ready()功能.无论如何,您都希望这样做能够优雅地退回到完全没有实现的浏览器上defer.)
Mar*_*p51 50
考虑这个答案已经过时了.有关较新浏览器版本的信息,请参阅此帖子上的其他答案.
基本上,defer告诉浏览器在执行该脚本块中的javascript之前等待"直到它准备好".通常这是在DOM完成加载和document.readyState == 4之后
延迟属性特定于Internet Explorer.在Internet Explorer 8中,在Windows 7上,我在JS Fiddle测试页面中看到的结果是1 - 2 - 3.
结果可能因浏览器而异.
http://msdn.microsoft.com/en-us/library/ms533719(v=vs.85).aspx
与流行的看法相反,IE比人们更频繁地遵循标准,实际上"延迟"属性在DOM Level 1规范中定义http://www.w3.org/TR/REC-DOM-Level-1/level -酮中将Html.HTML
W3C对延迟的定义:http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer:
"设置时,此布尔属性向用户代理提供一个提示,即脚本不会生成任何文档内容(例如,javascript中没有"document.write"),因此,用户代理可以继续解析和呈现."
由于defer属性仅适用于带有src的scripts标记.找到了一种模仿内联脚本延迟的方法.使用DOMContentLoaded事件.
<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
// Your inline scripts which uses methods from external-scripts.
});
</script>
Run Code Online (Sandbox Code Playgroud)
这是因为,在完全加载延迟属性脚本后,DOMContentLoaded事件将触发.
看看这篇优秀的文章深入探讨脚本加载的黑暗水域Google 开发人员 Jake Archibald 在 2013 年撰写的
\n引用该文章的相关部分:
\n\n\n推迟
\nRun Code Online (Sandbox Code Playgroud)\n<script src="//other-domain.com/1.js" defer></script>\n<script src="2.js" defer></script>\n规范说:一起下载,在 DOMContentLoaded 之前按顺序执行。在没有 \xe2\x80\x9csrc\xe2\x80\x9d 的脚本上忽略 \xe2\x80\x9cdefer\xe2\x80\x9d。
\nIE < 10 表示:我可能会在执行 1.js 的过程中执行 2.js。\xe2\x80\x99 是不是很有趣?
\n红色的浏览器说:我不知道 \xe2\x80\x9cdefer\xe2\x80\x9d 是什么,我\xe2\x80\x99m 将加载脚本,就好像它不在 \xe2\x80\x99t 那里一样。
\n其他浏览器说:好的,但我可能不会在没有 \xe2\x80\x9csrc\xe2\x80\x9d 的脚本上忽略 \xe2\x80\x9cdefer\xe2\x80\x9d 。
\n
(根据此评论,我将补充一点,早期版本的 Firefox 在defer脚本完成运行之前会触发 DOMContentLoaded 。)
现代浏览器似乎可以async正确支持,但您需要接受脚本无序运行并且可能在 DOMContentLoaded 之前运行。
小智 5
<script defer> -
\n一旦浏览器与带有 defer 的 script 标签交互
<script async> \xe2\x80\x94
\n一旦浏览器与 async 交互脚本标签
<script> \xe2\x80\x94
\n当浏览器与脚本标签交互时
| 归档时间: |
|
| 查看次数: |
112716 次 |
| 最近记录: |