我有一些<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属性只适用于带有src的脚本标签。找到了一种方法来模拟内联脚本的延迟。使用DOMContentLoaded事件。

<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
    // Your inline scripts which uses methods from external-scripts.
});
</script>

这是因为,DOMContentLoaded事件在延迟带属性脚本完全加载后触发。

其他回答

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

在概念上,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

因为defer属性只适用于带有src的脚本标签。找到了一种方法来模拟内联脚本的延迟。使用DOMContentLoaded事件。

<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
    // Your inline scripts which uses methods from external-scripts.
});
</script>

这是因为,DOMContentLoaded事件在延迟带属性脚本完全加载后触发。

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