首页  >  文章  >  web前端  >  对于Javascript加载的解析

对于Javascript加载的解析

不言
不言原创
2018-07-11 10:36:511259浏览

这篇文章主要介绍了关于对于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 = (&#39;https:&#39;==document.location.protocol ? &#39;https://ssl&#39; :  &#39;http:www&#39;) + &#39;.baidu.com/demo.js&#39;;
        var s = document.getElementsByTagName(&#39;script&#39;)[0];
        s.parentNode.insertBefore(script, s);
    };
)();

        这种方法是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件的触发问题。

        由于Javascript的动态性,还有很多异步加载方法:XHR Injection、XHR eval、Script In Iframe、document.write("