2016-04-28 61 views
5

Google Maps JavaScript执行一些沉重的DOM操作。即便如此,the fine docs建议与defer标志加载它:为什么使用Google Maps Javascript?

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script> 

为什么会defer标志来建议执行DOM操作的脚本? 我要求了解defer标志以及了解Google Maps API,因为我似乎对其中一个人正在做的事情有误解。

回答

12

通常,script标记会告诉浏览器停止解析HTML,取出脚本并运行它,然后继续解析HTML。这是因为脚本代码可能使用document.write输出到HTML令牌流。

async and defer都是告诉浏览器可以继续前进,并在下载脚本文件的同时继续解析HTML,并且不是马上运行脚本文件的机制。

虽然他们略有不同;从HTML规范的WHAT-WG版本the script section这张图是有用的设想的差异:以上

enter image description here

全部细节中的链接规范,但在短暂的,对“经典”的脚本(样你已经习惯了,但模块脚本即将推出):

  • 两个asyncdefer允许HTML的解析,继续无需等待脚本下载!
  • defer将使浏览器等待执行脚本,直到解析完成。
  • async只会让浏览器等到脚本下载完成,这意味着它可能会在解析完成之前或之后运行脚本,具体取决于下载何时完成(并记住它可能来自缓存)。
  • 如果async存在且受浏览器支持,则优先于defer
  • async脚本可以按任何顺序运行,无论它们在HTML中的显示顺序如何。
  • defer一旦解析完成,脚本将按它们在HTML中出现的顺序运行。
  • asyncdefer即使在半现代浏览器中也得到很好的支持,但在IE9和更早版本中没有正确支持,请参阅herehere

为什么会defer标志来建议执行DOM操作的脚本?

两个原因:

  1. 它使解析继续在脚本下载,
  2. 这意味着该脚本将不运行,直到解析完成。

如果你没有使用defer和你下script标签不很理想,使用defer帮助API脚本通过让浏览器完成建立DOM脚本试图操纵前,举止得体。

很多人还是把script标签文档的head部分,尽管这通常是把他们除非您使用defer(或async)最糟糕的地方。在大多数情况下,最好的地方(除非你有理由去做其他事情)在末尾,就在关闭</body>标签之前,以便A)您的网站快速呈现,无需等待脚本;和B)在您尝试操作DOM之前,DOM已经完全构建完成。推荐defer可能会将他们的script标签提前过早保存在HTML中,从而给他们带来麻烦。

+0

我想我明白了。所以看来,我阅读的文章(http://www.sitepoint.com/non-blocking-async-defer/)是为了理解延迟和异步属性**是完全错误的**,甚至**违反规范**。遗憾的是,它在Google上的排名非常高(https://google.com/?q=javascript+defer+async)。 – dotancohen

+0

@dotancohen:不,它是正确的,它只是说,“...不包含任何document.write或DOM修改nastiness:”时有点模糊。它应该*说的是类似于“...不包含任何document.write或DOM修改,意图与解析器内联运行。” (因为还有其他的东西你可以做,而不仅仅是'document.write',这将依赖于解析器等待你的脚本运行)。它不应该给人印象**所有** DOM修改都不在表格中。 –

2

谷歌地图示例同时使用asyncdefer标志。

  • async标志允许脚本在并行加载到DOM 解析,并作为API准备好立即执行。
  • defer标志允许脚本并行加载DOM 解析,但保证该脚本不会执行,直到 DOM完成解析。

async受现代HTML5浏览器支持,而defer支持是通用的。当标签一起使用时,defer只是旧版浏览器的后备版本,如果支持async,将被忽略。

在这些简单的例子中,或者async或者defer都可以工作,尽管这两者都不是必需的。在这种情况下,它仅用于性能。

参考文献:
Speed up Google Maps(and everything else) with async & defer
async vs defer attributes - Growing with the Web