同步加载: 即阻塞模式,会影响浏览器的后续处理,停止浏览器的后续解析,因此,会停止浏览器后续对文件(eg: img)的加载、渲染和执行。js 之所以要同步执行,是因为 js 中可能有输出 document 内容、修改dom、重定向等行为,所以默认同步执行才是安全的。
异步加载: 即非阻塞模式,浏览器在下载执行js的同时还会继续后续的处理。
常见的同步加载方式:
1、h5 中script的新属性 async 设定为false ,js文件将会以同步的方式加载。
2、html文件中的<script src='xxx.js'></script> js文件将会以同步的方式加载。如果xxx.js文件中有如下代码:
document.write('<script src='11.js'></script>'); document.write('<script src='22.js'></script>'); 那么 11.js以及22.js 都是以同步的方式加载的。
3、html中script标签之间的js代码 也是同步加载执行的。
<script>
//将会被同步加载执行的代码。
</script>
常见的异步加载方式:
1、任何以添加 script 节点(例如 appendChild(scriptNode) ) 的方式引入的js文件都是异步执行的 (scriptNode 需要插入document中,只创建节点和设置 src 是不会加载 js 文件的(IE6-9 除外),这跟 img 的预加载不能类比) ,无需特别设置script.type,如果过设置,需要设置为 javascript 类型,否则不会加载 js 文件(text/javascript ,或者带版本号的,如果有特殊需求)。
var script = document.createElement("script");
script.setAttribute("src","xx.js");
documenrt.getElementsByTagName("head")[0].appendChild(script);
xx.js 会在appendChild执行之后异步加载执行。
2、js代码包裹在匿名函数中并立即执行的方式是为了保护变量名泄露到外部可见,这是很常见的方式,尤其是在 js 库中被普遍使用。
(function()
{var po=document.createElement("script");
po.type="text/javascript"; po.async=true; po.src="aaa.js";
vars=document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(po,s);
})();
但是,这种加载方式在加载执行完之前会阻止 onload 事件的触发,而现在很多页面的代码都在 onload 时还要执行额外的渲染工作等,所以还是会阻塞部分页面的初始化处理。
3、onload是的异步加载
(function(){
function asuncLoad(){
var s= document.createElement('script');
s.type = 'text/javascript';
s.src = 'bbb.js';
var x = document.getElementByTagName('script')[0];
s.parentNode.insertBefore(s , x);
}
if(window.attchEvent){
window.attachEvent('onload', asyncLoad);
}else{
window.addEventListener('load', aysncLoad, false);
}
})();
它不是立即异步加载js 而是在onload的时候才开始异步加载,load的时候就是同步加载,就解决了onload事件在加载完整个js文件之后才触发的问题
二、async 和 defer 属性
1. defer 属性
defer属性声明这个脚本中将不会有 document.write 或 dom 修改。
浏览器将会并行下载 file.js 和其它有 defer 属性的script,而不会阻塞页面后续处理。
defer属性在IE 4.0中就实现了,超过13年了!Firefox 从 3.5 开始支持defer属性 。
注:所有的defer 脚本保证是按顺序依次执行的。
2. async 属性
async属性是HTML5新增的。作用和defer类似,但是它将在下载后尽快执行,不能保证脚本会按顺序执行。它们将在onload 事件之前完成。
Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支持 async 属性。可以同时使用 async 和 defer,这样IE 4之后的所有 IE 都支持异步加载。