关于js按需加载的依赖问题

  最近在做一个项目,作者使用jquery,由于原始jquery库中没有js按需加载,因此作者自己写了一个js按需加载的方法,方法如下

loadScript:function(urlArr,callBack){
		var _this = this;
		window.baseUrl = window.baseUrl || '';
		urlArr = $.map(urlArr,function(n){
			return window.baseUrl+n;
		});
		var scriptList = document.getElementsByTagName("script");  
        for (i = 0,max = scriptList.length; i < max; i++) {  
             if(urlArr.length===0){
				if($.isFunction(callBack)){
					callBack.call(window);
				}
				return;
			 }
			var index = $.inArray(scriptList[i].src,urlArr);
			if(index!==-1){
				urlArr.splice(index,1);
			}
        }
		if($.isArray(urlArr)){
			var length = urlArr.length;
			if(length===0){
				if($.isFunction(callBack)){
					callBack.call(window);
				}
				return;
			}
			else{
				loadOne(urlArr,callBack);
			}
		}
		function loadOne(urlArr,callBack){
			var url = urlArr.shift();
			var script = document.createElement("script");
			script.type="text/javascript";
			script.src = url;
			script.onload = script.onreadystatechange=function(){
				if(urlArr.length===0){
					if($.isFunction(callBack)){
						if (this.readyState && this.readyState == "loading")  
						return;  
						callBack.call(window);
					}
					return;
				}
				else{
					loadOne(urlArr,callBack);
				}
			};
			script.onerror=function(){
				throw new Error("load script:"+url+" error");
			};
			var scriptList = document.getElementsByTagName("script");
			document.getElementsByTagName("head")[0].appendChild(script);
		}
	},

 此方法的两个参数,第一个是js的数组,第二个为回调函数,此方法在高版本浏览器中相当正常(包括,IE10,chrome,火狐),但是在ie9一下包括ie9就出现问题,在script的onreadystatechange中出不去,一直在循环,然后作者很郁闷就询问了一个公司的大神,结果大神出手,便出现下面代码

function loadScript(urlArr,callBack){
		var _this = this;
		window.baseUrl = window.baseUrl || '';
		urlArr = $.map(urlArr,function(n){
			return window.baseUrl+n;
		});
		var scriptList = document.getElementsByTagName("script");  
        for (i = 0,max = scriptList.length; i < max; i++) {  
             if(urlArr.length===0){
				if($.isFunction(callBack)){
					callBack.call(window);
				}
				return;
			 }
			var index = $.inArray(scriptList[i].src,urlArr);
			if(index!==-1){
				urlArr.splice(index,1);
			}
        }
		if($.isArray(urlArr)){
			var length = urlArr.length;
			if(length===0){
				if($.isFunction(callBack)){
					callBack.call(window);
				}
				return;
			}
			else{
				loadOne(urlArr,callBack);
			}
		}
		function loadOne(urlArr,callBack){
			var url = urlArr.shift();
			var script = document.createElement("script");
			script.type="text/javascript";
			script.src = url;
			var exec = function(){
				if(urlArr.length===0){
					if($.isFunction(callBack)){
						callBack.call(window);
					}
				}
				else{
					loadOne(urlArr,callBack);
				}
			};
			if(script.attachEvent){
				script.attachEvent('onreadystatechange',function(){
					if(script.readyState == 'loaded' || script.readyState == 'complete') {
						exec();
						script.detachEvent('onreadystatechange',arguments.callee);
					}
				});
			} else {
				script.addEventListener('load',function(){
					exec();
					script.removeEventListener('load',arguments.callee,false);
				},false);
			}
			/*
			script.onload = script.onreadystatechange=function(){
				if(urlArr.length===0){
					if($.isFunction(callBack)){
						if (this.readyState && this.readyState == "loading")  
						return;  
						callBack.call(window);
					}
					return;
				}
				else{
					loadOne(urlArr,callBack);
				}
			};
			*/
			script.onerror=function(){
				throw new Error("load script:"+url+" error");
			};
			var scriptList = document.getElementsByTagName("script");
			document.getElementsByTagName("head")[0].appendChild(script);
		}
	}

 这两版代码的不同之处在于,大神的代码在执行完递归方法后,清除掉了script的onreadystatechange事件,如此便不会出现函数在scirpt的onreadystatechange事件中跑不出来了,但是笔者还是觉得不甘心,又在网上查了好久,也查了不少东西建议使用attachEvent 请记得 对于ie6 任何非 attachEvent方式注册的事件 (除硬编码写到html中的) 都会引起ie6 无法挽回的 跨页内存泄露. 至于多少 就看回调函数 所在闭包  中的数据量了. 作用域链 越深 受影响的东西 就越多...危害也就越大. 这篇文章中就讲明了这种方法的一些弊端,但是实在没办法,笔者只能舍弃小家为大家,放弃了ie6的速度而是选择其他浏览器的按需加载js。

    并且在写这个方法中,笔者发现大神朋友的方法中有一句arguments.callee,从来没用过的方法,百度一下,才发现原来这个是获取参数的原函数对象,大神犀利!!!至此这个方法引起的风波也告一段落了,但是本以为自己的js已经算是不错了,却发现还真是差得远,编程思想还是差得远,遇见棘手问题解决还是与大神有差距,需要努力啊!!!!

相关推荐