这几天因项目需求,要实现一系列的js文件加载的问题,因而,就按照常规思路写了一通,悲催的是测试后发现问题重重;javascript
为何会有这么多问题,仔细想来仍是对浏览器加载js的原理理解不透,因而我翻阅了大量的资料和本身的一些实践,总结出来如下的内容;html
一、js在浏览器中的阻塞java
常规理解就是浏览器在加载js时候会阻塞浏览器的渲染操做,但页面性能决定不但愿咱们在加载js的时候影响页面的渲染,因此咱们常常会把js文件放到body以前去加载。而不会把它放在head里去阻塞页面的渲染。那么问题来了,若是咱们把js放在head里,浏览器是怎么去执行它的呢,是按顺序加载仍是并行加载呢?跨域
其实在旧的浏览器下,都是按照前后顺序来加载的,这就保证了加载的js依赖不会发生问题。可是新的浏览器已经开始容许并行加载js了,也就是说我能够同时下载js文件,可是仍是前后顺序执行文件的。浏览器
二、document.write 使用app
咱们通常会用document.write来生成一段广告,常常这样操做:document.write('<script id="posAD" type="text/javascript" src="http://192.168.3.107:888/control.js?platformcode=tcy&postioncode=A1&filecode=10030"><\/script>');dom
这样操做也是阻塞的;有同窗就问了,你这是外联js,那么内链的呢,我也作过测试,同样的,一样会阻塞。异步
这样使用的时候必定要记住,要确保他是在dom ready以前去执行,不然它将会从新渲染整个页面。async
三、那么如何实现非阻塞呢,那么就须要动态加载js了,经过appendChild(script)这种方式去异步加载js了,其实还能够用xhr对象来处理,可是这样只能解决非跨域问题,跨域xhr就无能为力了。还有一种办法就是新浏览器的defer 和 async 属性了,这样你把它写到head里也不会阻塞浏览器的渲染了。post
因而在我明白上述的这样东东以后,我简单的实现一个动态加载js模块:
//loadJS模块 (function () { var loadJS = function (deps, callback) { if(typeof deps == 'string') { deps = [deps]; } var len = deps.length; var j = 0 ; var fn = function (){ j++; if(j == len) { callback.apply(window); } }; for(var i = 0 ; i < deps.length ; i++) { _loadMod(deps[i],fn); }; }; var _loadMod = function(url,fn) { var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement; var script = document.createElement('script'); script.type = 'text/javascript'; script.charset = 'utf-8'; script.async = true; script.src = url; script.onload = script.onreadystatechange = function() { if (!script.readyState || script.readyState in {'loaded': 1, 'complete': 1}) { script.onload = script.onreadystatechange = null; fn(); head.removeChild(script); script = null; } } head.insertBefore(script, head.firstChild); } window.loadJS = loadJS; })();
以上内容也是我这两天初步终结出来的,有不对的地方还但愿各位童鞋指正。
有兴趣的还能够参考这两篇博客:http://www.w3cfuns.com/blog-5443287-5401014.html 或则 http://www.cnblogs.com/hongcaomao/archive/2012/03/27/javascript_loadad.html