javascript中的defer和async学习+javascript执行顺序
一、defer和async
我们常用的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.
1、Defer
对于defer,我们可以先思考一个情况。一个页面如果有N个外链的脚本,放在head中,那么,当加载脚本时会阻塞页面的渲
染,也就是常说的空白。在简单的开发环境中,我们可能只要将源代码中的外链脚本位置换一下就ok了。可是面对越来越复杂的开发环境,前端同事如果要后台开
发同事调整一下脚本的位置,可能会花费大量的沟通成本和开发成本。我们可以使用defer这个属性。
如果一个script加了defer属性,即使放在head里面,它也会在html页面解析完毕之后再去执行,也就是类似于把这个script放在了页面底部。
2. Async
对于async,这个是html5中新增的属性,它的作用是能够异步的加载和执行脚本,不因为加载脚本而阻塞页面的加载。一旦加载到就会立刻执行。那async和defer有什么不同之处呢?
async 和 defer 标注的 script 都不会暂停HTML解析就立刻被下载,两者都支持onload事件回调来解决需要该脚本来执行的初始化。
3. 两者的区别在于执行时的不同:
async 脚本在script文件下载完成后会立即执行,并且其执行时间一定在 window的load事件触发之前。这意味着多个async脚本很可能不会按其在页面中的出现次序顺序执行。
与此相对,浏览器确保多个 defer 脚本按其在HTML页面中的出现顺序依次执行,且执行时机为DOM解析完成后,document的DOMContentLoaded 事件触发之前。
我们再看一下有async属性的情况,和defer一样,会等待的资源不会阻塞其余资源的加载,也不会影响页面的加载。但是有一点需要注意
下,在有async的情况下,js一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async,就很有可能出错。
这篇文章中总结了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) that async 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’s DOMContentLoaded event.
在上述的基础上,我根据实际使用的情况总结了一下defer和async的特征。
相同点:
- 加载文件时不阻塞页面渲染
- 对于inline的script无效
- 使用这两个属性的脚本中不能调用document.write方法
- 有脚本的onload的事件回调
区别点:
- html的版本html4.0中定义了defer;html5.0中定义了async
- 浏览器
Feature Chrome Firefox (Gecko) IE Opera Safari Basic support 1.0 1.0 (1.7 or earlier) Supported Supported Supported async attribute Supported 3.6 (1.9.2) 10 - 3.6 (1.9.2) defer attribute 3.6 (1.9.2) 3.5 (1.9.1) 4 - 3.6 (1.9.2)
除了基于Webkit的新版本浏览器,FireFox已经支持defer和onload属性很长时间了,而且从FF3.6开始添加了async属性。IE同样支持defer属性,但还不支持async属性,从IE9开始,onload属性也将被支持。
- 执行时刻
每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window的load事件之前执行。所以就有可能出现脚本执行 顺序被打乱的情况
每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的 DOMContentLoaded之前执行
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代码的合并和拆分,然后再根据页面需要使用这两个属性。
4、defer的注意事项和页面优化
加上 defer 等于在页面完全在入后再执行,相当于 window.onload ,但应用上比 window.onload 更灵活!
defer是脚本程序强大功能中的一个“无名英雄”。它告诉浏览器Script段包含了无需立即执行的代码,并且,与SRC属性联合使用,它还可以使这些脚本在后台被下载,前台的内容则正常显示给用户。
--但是 文档加载完毕了再执行脚本
一个常用的优化性能的方法是: 当脚本不需要立即运行时,在<SCRIPT>标签中设置“defer”属性。 (立即脚本没有被包含在一个function块中,因此会在加载过程中执行。) 设置“defer”属性后,IE就不必等待该脚本装载和执行完毕。这样页面加载会更快。一般来说,这也表明立即脚本最好放在function块中,并在 document或者body对象的onload 句柄中处理该函数。在有一些脚本需要依赖用户操作而执行时----例如点击按钮,或者移动鼠标到某个区域----使用该属性非常有用。但当有一些脚本需要 在页面加载过程中或加载完成后执行,使用defer属性得到的好处就不太大。
script中的defer属性默认情况下是false的。按照DHTML编程宝典中的描述,对于Defer属性是这样写的:
Using
the attribute at design time can improve the download performance of a
page because the browser does not need to parse and execute the script
and can continue downloading and parsing the page instead.
也就是说:如果是编写脚本的时候加入defer属性,那么浏览器在下载脚本的时候就不必立即对其进行处理,而是继续对页面进行下载和解析,这样会提高下载的性能。
这样的情况有很多种。比如你定义了很多javascript变量,或者在引用文件(.inc)中写了很多的脚本需要处理,那不妨在这些脚本中加入defer属性,对性能的提高肯定有所帮助。
- <script language="javascript" defer>
- var object = new Object();
- ....
- </script>
声明了defer属性之后,需要判断是否有别的变量引用了defer脚本块中的变量,否则的话会导致脚本错误的产生。
请注意两点:
1、不要在defer型的脚本程序段中调用document.write命令,因为document.write将产生直接输出效果。
2、而且,不要在defer型脚本程序段中包括任何立即执行脚本要使用的全局变量或者函数。
================说明: 华丽丽的分割线===============
对于znxds提出的IE下的工作,我针对FF和IE6、IE7、IE8下面做了比较
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中无效。
二、javascript执行顺序
js的执行顺序基本上按照在html中出现的顺序,但是也有一些细小的变化。
- 首先执行<head>标签中的js,不论是内置还是外链形式,都是按照出现的顺序执行。
- 接着执行body中的脚本,按顺序直到<html>标签外。
- 然后执行defer="defer"的脚本。(IE中测试支持,chrome和firefox都不支持defer属性,在这两个浏览器中,将作为正常的脚本段按顺序执行)。
- 最后执行body的onload方法b()。
说明: javaScript执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且在分析执行同一段代码中,定义式的函数语句会被提取出来优先执行。函数定义执行完后,才会按顺序执行其他代码。
例子1
- <script>
- var hello = function(){
- alert('hello,zhangsan');
- }
- hello();//第一次调用,输出“hello,zhangsan”
- var hello = function(){
- alert('hello,lisi');
- }
- hello();//第二次调用,输出“hello,lisi”
- <script>
例子2
- <script type="text/javascript">
- function hello(){
- alert('hello,zhangsan');
- }
- hello(); //第一次调用,输出hello,lisi
- function hello(){
- alert('hello,lisi');
- }
- hello();//第二次调用,输出hello,lisi
- </script>
两次调用都会输出相同的内容“hello,lisi”。同样是声明两个相同名称的函数,为什么调用的结果却不一样呢?
这 就是JavaScript执行顺序导致的。JavaScript执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且在分析执行同一段 代码中,定义式的函数语句(JS中函数是第一公民)总是会被提取出来优先执行。函数定义执行完后,才会按顺序执行其他代码。也就是说,在第一次调用hello函数之前,第一个函数语句 定义的代码已经被第二个函数定义语句的代码覆盖了,这就是为什么在例子2中第一次调用hello时,也会输出后面定义的函数内容的原因了。
例子3
- <script type="text/javascript">
- function hello(){
- alert('hello,zhangsan');
- }
- hello();//第一次调用,输出hello,zhangsan
- </script>
- <script>
- function hello(){
- alert('hello,lisi');
- }
- hello();//第二次调用,输出hello,lisi
- </script>
两次调用分别在两个不同的代码段内,所以互不影响。
参考:
- 常用的script标签:defer和async
- http://dev.w3.org/html5/spec/Overview.html#attr-script-async
- javascript执行顺序
- js执行顺序
- javascript中defer的作用
javascript中的defer和async学习+javascript执行顺序的更多相关文章
- Javascript中页面加载完成后优先执行顺序
Javascript中页面加载完成后优先执行顺序 document优先于windowwindow优先于element //document加载完成执行方法体 document.addEventList ...
- 对于javaScript中的alert和document.write()的执行顺序的记录
代码: <script>//1----语句式的匿名函数创建以及调用 (function(name,age){ alert("name:"+name+",age ...
- 浅谈JavaScript中的defer,async
引言 开始重读<<JavaScript高级程序设计>>一书,看到关于JavaScript中关于defer.async的部分.网上查询了点资料,觉得蛮好的.现在总结下. defe ...
- 脚本引用中的defer和async的用法和区别
之前的博客漫谈前端优化中的引用资源优化曾经提到过脚本引用异步设置defer.async,没有细说,这里展开一下,谈谈它们的作用和区别,先上张图来个针对没用过的小伙伴有个初始印象: 是的,就是在页面脚本 ...
- 2、JavaScript 基础二 (从零学习JavaScript)
11.强制转换 强制转换主要指使用Number.String和Boolean三个构造函数,手动将各种类型的值,转换成数字.字符串或者布尔值. 1>Number强制转换 参数为原始类型值的转换规 ...
- 1、JavaScript 基础一 (从零学习JavaScript)
1:定义:javascript是一种弱类型.动态类型.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类 ...
- javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的。
javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的. 1 function getUrl(tp) { if (tp == 'd') { ...
- javascript中的defer是什么?
今天看到stackoverflow上的这样一个问题(问题链接),大概是说用jQuery获取不到元素,这是我们刚开始接触javascript常常会碰到的问题,回答者列举了4中方法去解决获取不到元素的问题 ...
- JavaScript 中的undefined and null 学习
JavaScript 中的undefined and null learn record from the definitive guide to html5 JavaScript 中有两个特殊值:u ...
随机推荐
- CUBRID学习笔记 47 show
cubrid的中sql查询语法show c#,net,cubrid,教程,学习,笔记欢迎转载 ,转载时请保留作者信息.本文版权归本人所有,如有任何问题,请与我联系wang2650@sohu.com . ...
- SQL SERVER赋权限
--创建登录账户 use master GO EXEC sp_addlogin 'jacky', 'pwd' --EXEC sp_droplogin 'jacky' --删除登陆账户 use Test ...
- php提高程序效率的24个小技巧
本文转自<php必须知道的300个问题>一书,在此记录方便以后查看 (1)用单引号代替双引号来包含字符串,这样做会更快些.因为php会在双引号包围的字符串中搜寻变量,单引号则不会.注意:只 ...
- win10系统更新补丁时进度条一直卡在0%不动的解决方案
为了能够让win10系统更加安全稳定,很多用户都会时不时为自己的电脑安装补丁.不过,部分用户在为win10系统更新补丁时,却会遇到进度条一直卡在0%不动的问题.这该怎么办呢?下面,小编就告诉大家解决该 ...
- epoll的lt和et模式的实验
针对epoll api的两种触发模式,lt和et,仿照一些例子写了代码进行实验. #include <sys/types.h> #include <sys/socket.h> ...
- Android控件之CheckBox(复选框控件)
一.有两种状态: 选中状态(true).未选中状态(false) 二.属性 android:id = "@+id/checkbox" android:layout_width=&q ...
- datagrid实现行的上移和下移
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- hiho_1081_最短路径1
题目 最短路模板题目,纯练习手速. 实现 #include<iostream> #include<string.h> #include<iostream> #inc ...
- Python类属性详解
在python开发中,我们常常用到python的类,今天就通过实例和大家扒一扒类的属性,一起来看看吧. 类属性 1.类定义后就存在,而且不需要实例化 2.类属性使得相同类的不同实例共同持有相同变量 类 ...
- ActionErrors 使用说明 struts1 validate 处理流程 详细教程(转)
转自(http://blog.csdn.net/wyx100/article/details/8736445). struts1 处理流程是 jsp --> ActionForm 中的A ...