我有一些<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?


当前回答

<脚本延迟> - 只要浏览器使用defer与脚本标记进行交互

它开始获取脚本文件,同时还并排解析HTML。 在这种情况下,脚本只在HTML解析完成后执行。

<脚本async> - 当浏览器与async交互脚本标记时

它在并排解析HTML时开始获取脚本文件。 但是在完全获取脚本时停止HTML解析,然后开始执行脚本,之后继续进行HTML解析。

<脚本> - - - 只要浏览器与脚本标记交互

它停止HTML的解析,获取脚本文件, 在本例中,执行脚本,然后继续解析HTML。

其他回答

真正的答案是:因为你不能相信拖延。

在概念上,defer和async的区别如下:

Async允许脚本在后台下载而不会阻塞。然后,当它完成下载时,呈现被阻塞,脚本执行。执行脚本后继续渲染。

Defer也做同样的事情,只是声明保证脚本按照页面上指定的顺序执行,并且在文档完成解析后执行。因此,有些脚本可能会完成下载,然后等待稍后下载但在它们之前出现的脚本。

不幸的是,由于真正的标准之争,defer的定义因规范而异,甚至在最新的规范中也没有提供有用的保证。正如这里的答案和这个问题所展示的,浏览器实现的defer不同:

在某些情况下,某些浏览器存在导致延迟脚本无序运行的错误。 有些浏览器将DOMContentLoaded事件延迟到延迟脚本加载之后,而有些浏览器则不会。 有些浏览器使用内联代码而不带src属性来遵从<script>元素,有些浏览器则忽略它。

幸运的是,规范至少指定了异步覆盖延迟。所以你可以将所有脚本视为异步,并获得大量的浏览器支持,如下所示:

<script defer async src="..."></script>

全球98%的浏览器和99%的美国浏览器将使用这种方法避免阻塞。

(如果您需要等待文档完成解析,请侦听事件DOMContentLoaded事件或使用jQuery方便的.ready()函数。无论如何,你都希望这样做,以优雅地返回到根本没有实现defer的浏览器上。)

defer属性是一个布尔属性。

当出现时,它指定当页面完成解析时执行脚本。

注意:defer属性仅用于外部脚本(应该仅在src属性存在时使用)。

注意:有几种方式可以执行外部脚本:

如果出现async:脚本将与页面的其余部分异步执行(在页面继续解析时将执行脚本) 如果async不存在,而defer存在:当页面完成解析时执行脚本 如果async和defer都不存在:在浏览器继续解析页面之前,立即获取并执行脚本

还应该注意的是,在IE<=9中,在某些情况下使用脚本延迟可能会出现问题。更多相关信息:https://github.com/h5bp/lazyweb-requests/issues/42

更新: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:

当设置时,这个布尔属性向用户代理提供了一个提示,提示脚本不会生成任何文档内容(例如,没有“文档”。这样,用户代理就可以继续解析和渲染了。

defer属性仅用于外部脚本(只有在src属性存在时才应该使用)。