通常,script
标记会告诉浏览器停止解析HTML,取出脚本并运行它,然后继续解析HTML。这是因为脚本代码可能使用document.write
输出到HTML令牌流。
async
and defer
都是告诉浏览器可以继续前进,并在下载脚本文件的同时继续解析HTML,并且不是马上运行脚本文件的机制。
虽然他们略有不同;从HTML规范的WHAT-WG版本the script
section这张图是有用的设想的差异:以上
全部细节中的链接规范,但在短暂的,对“经典”的脚本(样你已经习惯了,但模块脚本即将推出):
- 两个
async
和defer
允许HTML的解析,继续无需等待脚本下载!
defer
将使浏览器等待执行脚本,直到解析完成。
async
只会让浏览器等到脚本下载完成,这意味着它可能会在解析完成之前或之后运行脚本,具体取决于下载何时完成(并记住它可能来自缓存)。
- 如果
async
存在且受浏览器支持,则优先于defer
。
async
脚本可以按任何顺序运行,无论它们在HTML中的显示顺序如何。
defer
一旦解析完成,脚本将按它们在HTML中出现的顺序运行。
async
和defer
即使在半现代浏览器中也得到很好的支持,但在IE9和更早版本中没有正确支持,请参阅here和here。
为什么会defer
标志来建议执行DOM操作的脚本?
两个原因:
- 它使解析继续在脚本下载,
- 这意味着该脚本将不运行,直到解析完成。
如果你没有使用defer
和你下script
标签不很理想,使用defer
帮助API脚本通过让浏览器完成建立DOM脚本试图操纵前,举止得体。
很多人还是把script
标签文档的head
部分,尽管这通常是把他们除非您使用defer
(或async
)最糟糕的地方。在大多数情况下,最好的地方(除非你有理由去做其他事情)在末尾,就在关闭</body>
标签之前,以便A)您的网站快速呈现,无需等待脚本;和B)在您尝试操作DOM之前,DOM已经完全构建完成。推荐defer
可能会将他们的script
标签提前过早保存在HTML中,从而给他们带来麻烦。
我想我明白了。所以看来,我阅读的文章(http://www.sitepoint.com/non-blocking-async-defer/)是为了理解延迟和异步属性**是完全错误的**,甚至**违反规范**。遗憾的是,它在Google上的排名非常高(https://google.com/?q=javascript+defer+async)。 – dotancohen
@dotancohen:不,它是正确的,它只是说,“...不包含任何document.write或DOM修改nastiness:”时有点模糊。它应该*说的是类似于“...不包含任何document.write或DOM修改,意图与解析器内联运行。” (因为还有其他的东西你可以做,而不仅仅是'document.write',这将依赖于解析器等待你的脚本运行)。它不应该给人印象**所有** DOM修改都不在表格中。 –