关于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已经算是不错了,却发现还真是差得远,编程思想还是差得远,遇见棘手问题解决还是与大神有差距,需要努力啊!!!!