我有一些<script>元素,其中一些代码依赖于其他<script>元素中的代码。我看到defer属性在这里可以派上用场,因为它允许延迟代码块的执行。
为了测试它,我在Chrome上执行了这个:http://jsfiddle.net/xXZMN/。
<script defer="defer">alert(2);</script>
<script>alert(1)</script>
<script defer="defer">alert(3);</script>
然而,它提醒2 - 1 - 3。为什么它不提醒1 - 2 - 3?
更新:2/19/2016
这个答案已经过时了。有关更新的浏览器版本的信息,请参考这篇文章中的其他答案。
基本上,defer告诉浏览器在执行脚本块中的javascript之前等待“直到它准备好了”。这通常发生在DOM完成加载和文档之后。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遵循标准的情况相反,实际上“defer”属性是在DOM级别1规范http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html中定义的
W3C对defer的定义:http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer:
当设置时,这个布尔属性向用户代理提供了一个提示,提示脚本不会生成任何文档内容(例如,没有“文档”。这样,用户代理就可以继续解析和渲染了。
HTML5规范中的一些片段:http://w3c.github.io/html/semantics-scripting.html#element-attrdef-script-async
必须使用defer和async属性
如果SRC属性没有被指定
不存在。
There are three possible modes that
can be selected using these
attributes [async and defer]. If the async attribute is
present, then the script will be
executed asynchronously, as soon as it
is available. If the async attribute
is not present but the defer attribute
is present, then the script is
executed when the page has finished
parsing. If neither attribute is
present, then the script is fetched
and executed immediately, before the
user agent continues parsing the page.
The exact processing details for these
attributes are, for mostly historical
reasons, somewhat non-trivial,
involving a number of aspects of HTML.
The implementation requirements are
therefore by necessity scattered
throughout the specification. The
algorithms below (in this section)
describe the core of this processing,
but these algorithms reference and are
referenced by the parsing rules for
script start and end tags in HTML, in
foreign content, and in XML, the rules
for the document.write() method, the
handling of scripting, etc.
如果元素有src属性,
元素有一个defer属性,
元素被标记为
"parser-inserted"和元素
没有async属性:
元素必须添加到脚本列表的末尾
当文档完成时执行
与文档相关的解析
对象的解析器的
元素。
真正的答案是:因为你不能相信拖延。
在概念上,defer和async的区别如下:
Async允许脚本在后台下载而不会阻塞。然后,当它完成下载时,呈现被阻塞,脚本执行。执行脚本后继续渲染。
Defer也做同样的事情,只是声明保证脚本按照页面上指定的顺序执行,并且在文档完成解析后执行。因此,有些脚本可能会完成下载,然后等待稍后下载但在它们之前出现的脚本。
不幸的是,由于真正的标准之争,defer的定义因规范而异,甚至在最新的规范中也没有提供有用的保证。正如这里的答案和这个问题所展示的,浏览器实现的defer不同:
在某些情况下,某些浏览器存在导致延迟脚本无序运行的错误。
有些浏览器将DOMContentLoaded事件延迟到延迟脚本加载之后,而有些浏览器则不会。
有些浏览器使用内联代码而不带src属性来遵从<script>元素,有些浏览器则忽略它。
幸运的是,规范至少指定了异步覆盖延迟。所以你可以将所有脚本视为异步,并获得大量的浏览器支持,如下所示:
<script defer async src="..."></script>
全球98%的浏览器和99%的美国浏览器将使用这种方法避免阻塞。
(如果您需要等待文档完成解析,请侦听事件DOMContentLoaded事件或使用jQuery方便的.ready()函数。无论如何,你都希望这样做,以优雅地返回到根本没有实现defer的浏览器上。)
This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed. Since this feature hasn't yet been implemented by all other major browsers, authors should not assume that the script’s execution will actually be deferred. Never call document.write() from a defer script (since Gecko 1.9.2, this will blow away the document). The defer attribute shouldn't be used on scripts that don't have the src attribute. Since Gecko 1.9.2, the defer attribute is ignored on scripts that don't have the src attribute. However, in Gecko 1.9.1 even inline scripts are deferred if the defer attribute is set.
延迟工作与chrome, firefox, ie > 7和Safari
裁判:https://developer.mozilla.org/en-US/docs/HTML/Element/script
看看谷歌开发人员Jake Archibald在2013年写的这篇深入研究脚本加载的文章。
引用该条有关部分:
Defer
<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>
Spec says: Download together, execute in order just before DOMContentLoaded. Ignore “defer” on scripts without “src”.
IE < 10 says: I might execute 2.js halfway through the execution of 1.js. Isn’t that fun??
The browsers in red say: I have no idea what this “defer” thing is, I’m going to load the scripts as if it weren’t there.
Other browsers say: Ok, but I might not ignore “defer” on scripts without “src”.
(根据这条评论,我将添加早期版本的Firefox在延迟脚本完成运行之前触发DOMContentLoaded。)
现代浏览器似乎正确地支持异步,但您需要接受脚本无序运行,并且可能在DOMContentLoaded之前运行。
<脚本延迟> -
只要浏览器使用defer与脚本标记进行交互
它开始获取脚本文件,同时还并排解析HTML。
在这种情况下,脚本只在HTML解析完成后执行。
<脚本async> -
当浏览器与async交互脚本标记时
它在并排解析HTML时开始获取脚本文件。
但是在完全获取脚本时停止HTML解析,然后开始执行脚本,之后继续进行HTML解析。
<脚本> - - -
只要浏览器与脚本标记交互
它停止HTML的解析,获取脚本文件,
在本例中,执行脚本,然后继续解析HTML。