这篇文章主要介绍了关于对于Javascript加载的解析,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
1. 浏览器加载
(1) 同步加载
在网页中,浏览器加载js文件的方式是通过3f1c4e4b6b16bbbd69b2ee476dc4f83a标签。如下所示:
//内嵌脚本 <script type="text/javacript"> // code here! </script> //加载外部脚本 <script type="text/javascript src="path/demo.js"></script>
3f1c4e4b6b16bbbd69b2ee476dc4f83a标签很方便,只要加入后,浏览器便可读取并运行,但是在读取的时候,浏览器是按照3f1c4e4b6b16bbbd69b2ee476dc4f83a标签的出现顺序,读取Javascript文件,然后立即运行,导致在多个文件相互依赖的情况下,依赖性最小的文件必须放在最前面,依赖性最大的必须放在最后面,否则代码会报错,这一点,想必大家在使用bootstrap的时候都深有体会。另一方面,浏览器采用同步模式加载3f1c4e4b6b16bbbd69b2ee476dc4f83a标签,也就是说,页面会等待JavaScript文件加载完成,然后再运行后面的代码。当存在很多个3f1c4e4b6b16bbbd69b2ee476dc4f83a标签时,浏览器无法同时读取,必须读完一个再读取另一个,造成读取时间大大延长,页面响应缓慢,影响用户体验。同步模式又称阻塞模式,会阻止浏览器的后续处理,停止后续的解析,只有当前加载完成,才能进行下一步操作,所以默认同步执行才是安全的。但这样如果js中有输出document内容、修改DOM、重定向等行为,就会造成阻塞。所以一般建议把3f1c4e4b6b16bbbd69b2ee476dc4f83a标签放在6c04bd5ca3fcae76e30b72ad730ca86d结尾处,这样能减少页面阻塞。
(2)异步加载
为了解决这一问题,ES5中采用了DOM方法,动态加载JavaScript脚本文件。
function loadScript(url) { var script = document.createElement("script"); script.type="text/javascript"; script.src=url; document.body.appendChild(script); }
这种方式通过创建一个新的3f1c4e4b6b16bbbd69b2ee476dc4f83a标签,并设置其src属性,异步读取javacript文件
这样不会造成页面阻塞,但会有另一个问题,如果其他脚本文件依赖于它,此时无法保证此脚本什么时候能够载入完毕。
另一种加载方式是利用defer和async属性,使脚本异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。defer和async的区别是: defer要等到整个页面在内存中正常渲染结束(DOM结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完成,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。即defer是渲染完再执行,async是下载完就执行。另外,如果有多个defer脚本,会按照它们在页面中出现的顺序加载,而多个async脚本是不能保证加载顺序的。
IE9及以下版本在延迟实现方面存在一些相当糟糕的错误,导致执行顺序无法保证。 如果你需要支持c0b81e2d7e107151c9db0ab74d32bb012cacc6d41bbb37262a98f745aa00fbf0 27893951ee31aa4ab68c289425ee4a992cacc6d41bbb37262a98f745aa00fbf0
如何选用defer和async。如果使用的script是个模块,并且不依赖任何其它script文件时使用async;如果该脚本依赖其它script或则被其它script依赖,就使用defer;倘若脚本文件很小且被一个async script依赖,就使用内嵌script把该文件放在所有async script前面。
另外一种方法是onload事件的异步加载。
(function(){ if(window.attachEvent) { window.attachEvent("load", asyncLoad); } else if(window.addEventListener) { window.addEventListener("load", asyncLoad); } else { window.onload = asyncLoad; } var asyncLoad = function() { var script = document.createElement("script"); script.type="text/javascript"; script.async = true; script.src = ('https:'==document.location.protocol ? 'https://ssl' : 'http:www') + '.baidu.com/demo.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(script, s); }; )();
这种方法是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件的触发问题。
由于Javascript的动态性,还有很多异步加载方法:XHR Injection、XHR eval、Script In Iframe、document.write("