我们常用的script标签,有两个和性能、js文件下载执行相关的属性:defer和async

defer的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】

This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed.

async的含义【摘自https://developer.mozilla.org/En/HTML/Element/Script】

Set this Boolean attribute to indicate that the browser should, if possible, execute the script asynchronously.

Defer

对于defer,我们可以先思考一个情况。一个页面如果有N个外链的脚本,放在head中,那么,当加载脚本时会阻塞页面的渲染,也就是常说的空白。在简单的开发环境中,我们可能只要将源代码中的外链脚本位置换一下就ok了。可是面对越来越复杂的开发环境,前端同事如果要后台开发同事调整一下脚本的位置,可能会花费大量的沟通成本和开发成本。我在去年的一个项目中就遇到过此类情况,当然也很感谢当时的后台开发同事的配合,他们都辛辛苦苦的调整了脚本的位置,解决了空白的问题。

那么可以让这个成本降到最低吗?那么我们可以使用defer这个属性。

如果一个script加了defer属性,即使放在head里面,它也会在html页面解析完毕之后再去执行,也就是类似于把这个script放在了页面底部。

关于defer有两个demo:

  • without defer
  • with defer

简单介绍一下这个demo,一共引用了3个js和1个css,为了能更好的展示defer的效果,第二个js-2.php是延迟了3秒返回的。1.js会在页面中生成一个值为1的input框,2.php会生成值为2的input框,3.js会生成值为3的input框。一方面我们需要观察页面渲染的时间,另一方面我们也要看一下js是否顺序执行了。

下图是without_defer.html的效果,从瀑布图可以看出,domready和onload的时间都在6s左右,因为需要等待2.php的返回才能渲染页面。如果你访问上面的例子,可以看出,页面要等6s的时间才会呈现出来,6s之前都是空白。

那么如果我们为每个js都加上defer属性,请看下面两张图

第一张是在加载过程中截取的,可以看到一旦有了defer属性,虽然有资源2.php需要等待,但是仍然会继续渲染页面,加载后续的js和css等资源文件。对比上面的情况,可以看到domready的时间明显提前,如果你访问demo地址,会发现页面会照常渲染出来,只不过2.php里面的内容会延迟执行。

从上面的对比可以看出,对于defer,我们可以认为是将外链的js放在了页面底部。js的加载不会阻塞页面的渲染和资源的加载。不过defer会按照原本的js的顺序执行,所以如果前后有依赖关系的js可以放心使用。

Async

对于async,这个是html5中新增的属性,它的作用是能够异步的加载和执行脚本,不因为加载脚本而阻塞页面的加载。一旦加载到就会立刻执行。那async和defer有什么不同之处呢?我们还是先看async的两个demo

  • without async
  • with async

demo的效果和上面描述的一样。

下图是without async的瀑布图,和没有defer的情况是一样的。domready和load的时间都因为一个js的延迟而延迟了。

我们再看一下有async属性的情况,和defer一样,会等待的资源不会阻塞其余资源的加载,也不会影响页面的加载。但是有一点需要注意下,在有async的情况下,js一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就很有可能出错。

Difference

这篇文章中总结了defer和async的相同点和区别。

Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script. The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window’s load event. This means it’s possible (and likely) thatasync scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document’sDOMContentLoaded event.

Wrapping it up

在上述的基础上,我根据实际使用的情况总结了一下defer和async的特征。
相同点:

  • 加载文件时不阻塞页面渲染
  • 对于inline的script无效
  • 使用这两个属性的脚本中不能调用document.write方法
  • 有脚本的onload的事件回调

区别点:

  • html的版本html4.0中定义了defer;html5.0中定义了async
  • 浏览器
    Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
    Basic support 1.0 1.0 (1.7 or earlier) (Supported) (Supported) (Supported)
    asyncattribute (Supported) 3.6 (1.9.2) 10 (Supported)
    deferattribute (Supported) 3.5 (1.9.1) 4 (Supported)
  • 执行时刻
    每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window的load事件之前执行。所以就有可能出现脚本执行顺序被打乱的情况;每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的DOMContentLoaded之前执行。

摘自【http://dev.w3.org/html5/spec/Overview.html#attr-script-async】

There are three possible modes that can be selected using these attributes. 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.

简单的来说,使用这两个属性会有三种可能的情况

  • 如果async为true,那么脚本在下载完成后异步执行。
  • 如果async为false,defer为true,那么脚本会在页面解析完毕之后执行。
  • 如果async和defer都为false,那么脚本会在页面解析中,停止页面解析,立刻下载并且执行,

最后给一点个人的建议,无论使用defer还是async属性,都需要首先将页面中的js文件进行整理,哪些文件之间有依赖性,哪些文件可以延迟加载等等,做好js代码的合并和拆分,然后再根据页面需要使用这两个属性。

本文another链接:http://feifeipan.sinaapp.com/?p=51

=====华丽丽的分割线=========

对于znxds提出的IE下的工作,我针对FF和IE6、IE7、IE8下面做了比较。

demo

Firefox中,inline的defer是没有效果的;outer的defer会在页面最底部执行。

IE8.0中,inline和outer的defer是起作用的,都会延迟到页面底部,排在其他非defer的js后面执行

IE7.0的情况,和IE8.0一致。

IE6.0中,关于defer inline js,要区分是在head中还是在body中。在head中defer inline js会在遇到body之后优先执行,而在body中的defer inline js会在body结束之前执行;关于defer outer js, 依然是在页面最后执行。

所以可以看出,defer的outer js在各种浏览器中表现一致;defer的inline js在IE6中比较特殊,head和body中的顺序不一样,IE7和IE8会延迟到页面底部执行,在Firefox中无效。

本文作者:小灰灰 转载请注明来自:携程UED

转载于:https://www.cnblogs.com/human/p/3419737.html

script的defer和async相关推荐

  1. JS中script标签defer和async属性的区别

    向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一种直接在script标签之间插入js代码,第二种即是通过src属性引入外部js文件.由于解释器在解 ...

  2. script 脚本标签中 defer 和 async (延缓 和 异步)

    原文章:https://segmentfault.com/q/1010000000640869 本文章讲解几个点: <script>  标签中 的 defer 和 async 是什么: 使 ...

  3. defer和async的原理与区别

    上一篇刚转载了一篇有关于网站性能优化的文章,其中提及到了页面的加载和渲染的过程,提到了defer和async的相关区别,但是本人在此之前并没有深究其中的区别. defer和async是script标签 ...

  4. 浅谈script标签中的async和defer

    script标签用于加载脚本与执行脚本,在前端开发中可以说是非常重要的标签了. 直接使用script脚本的话,html会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM渲 ...

  5. script标签中的async和defer

    在程序中代码是一行一行执行的,html标签都是由渲染引擎来执行,代码执行时从上往下一行一行执行,当执行到alert(如下图),alert会阻塞后面代码的执行,当点击完确定之后,代码继续往下执行. ja ...

  6. script标签中defer和async的区别

    defer 和 async属性都是去异步加载外部的JS脚本文件,它们都不会阻塞页面的解析,其区别如下: defer为true:延迟加载脚本,在文档完成解析完成开始执行,并且在DOMContentLoa ...

  7. script标签中的defer和async属性

    默认情况下,浏览器是同步加载 JavaScript 脚本,即渲染引擎遇到<script>标签就会停下来,等到执行完脚本,再继续向下渲染.如果是外部脚本,还必须加入脚本下载的时间. 如果脚本 ...

  8. script 标签中的defer 和 async 属性

    浏览器在解析 HTML 的时候,如果遇到一个没有任何属性的 <script> 标签 ,就会暂停解析,先发送网络请求获取该 JS 脚本的代码内容,然后让 JS 引擎执行该代码,当代码执行完毕 ...

  9. script 标签上的 defer 和 async 属性是什么?

    我们经常使用 script 标签向页面插入一个常规的 JavaScript 文件: <script src="/path/to/script.js"></scri ...

最新文章

  1. nvidia旧版驱动_N卡用户注意:老版驱动存在5个高危漏洞,赶紧更新
  2. p187让元素垂直居中
  3. 别再纠结线程池大小/线程数量了,没有固定公式的
  4. 微信小程序button授权页面,用户拒绝后仍可再次授权
  5. 2018湖湘杯web、misc记录
  6. 华为手机像素密度排行_2020上半年手机芯片十大排行:华为麒麟990第四,骁龙865第一...
  7. 【转载】从头编写 asp.net core 2.0 web api 基础框架 (1)
  8. mysql数据库sql注入原理_sql注入原理详解(一)
  9. 嵌入式Linux入门5:移植总览
  10. indexed true mysql_一行代码,搞定浏览器数据库 IndexedDB
  11. matlab在振动信号处理中的应用_激光测振仪在超声变幅杆振动测试中的应用
  12. 61850客户端软件构建
  13. 方便简洁的在线WEB多人网页聊天室系统源码
  14. 新浪微博开发者平台应用申请及配置说明
  15. python数字转英文_GitHub - Ailln/en2an: 快速转化「英文数字」和「阿拉伯数字」
  16. 网页制作:制作一个官网
  17. (亲测可用)如何在Win10家庭版中找回组策略编辑器
  18. matplotlib中cmap_Matplotlib:imshow中cmap的功能是什么?
  19. Element开发页面没有数据时,展示占位图片
  20. 世界上为什么有那么多的不幸的人

热门文章

  1. Linux下搭建FTP服务器笔记
  2. 收集很实用的 Linux 高级命令
  3. 程序人生:给程序员的18个建议
  4. php 点击之后保留样式,通过不修改arc.archives.class.php而保留原有样式调上一篇下一篇...
  5. java 不重启部署_编译Java类后不重启Tomcat有两种方式:热部署、热加载
  6. [python 进阶] 9. 符合Python风格的对象
  7. 怎么实现页面友好跳转_如何实现软,友好和一致的UI设计
  8. 面试官问:JS的继承
  9. 计算机协会丨让技能得到提升,让思维受到启迪
  10. 刺猬文│从启动方式来看播客链的运行机制—设置验证者