要求:
根據下面的配置文件
復制代碼 代碼如下:
module=[
{'name':'jquery','src':'/js/lib/jquery-1.8.3.js'},
{'name':'swfobject','src':'/js/utils/swfobject.js'},
{'name':'fancybox','src':'/js/jquery/jquery.fancybox.js','require':['jquery']},
{'name':'uploadify','src':'/js/utils/uploadify.js','require':['swfobject']},
{'name':'jqform','src':'/js/jquery/jquery.form.js','require':['jquery']},
{'name':'register','src':'/js/page/reg.js','require':['jqform']},
{'name':'login','src':'/js/page/login.js','require':['fancybox','jqform']},
{'name':'upload','src':'/js/page/upload.js','require':['fancybox','jqform','uploadify']}
]
寫一個函數
def getfiles(name)
返回 加載某個name指定的頁面,要加載的js文件列表,有依賴的要先加載
小菜解法
此題粗看起來很簡單,實則不然。
難點在於依賴模塊的加載時機。假如有這樣的依賴關系:A-B&C、B-C,A模塊依賴B模塊和C模塊,同時B模塊又依賴了C模塊,總不能讓C加載兩次吧!
小菜給出的這個解法,只是一個思路,肯定有比這更好的算法,小菜覺得可以用二叉樹之類的算法解決,但小菜不會呀~~~
此算法沒有考慮循環依賴的情景。
代碼如下:
復制代碼 代碼如下:
/**
* 不考慮循環依賴
* @type {Function}
*/
var loadModule = (function(){
/**
* 業務邏輯封裝
* @type {{chainHead: {}, chainCurrent: {}, srcCache: {}, main: main, load: load, findModule: findModule}}
*/
var logics = {
chainHead: {}, //鏈表頭
chainCurrent: {}, //鏈表當前節點
srcCache: {}, //module src 緩存
/**
* 對外接口
* @param modules 配置對象
* @param name 模塊名稱
* @returns {Array} 依賴模塊列表,按照加載先後順序排列
*/
main: function(modules, name){
var nameArray = [], //模塊名稱列表
srcArray = [], //依賴模塊列表
nameStr = "", //模塊名稱字符串集
repeatRegex = /(^| )([\w]+ ).*\2/, //模塊名稱去重正則
i = 0;
//粗略加載所有依賴模塊
this.load(modules, name)
//構造模塊名稱字符串集
this.chainCurrent = this.chainHead;
while(this.chainCurrent.next){
nameArray.push(this.chainCurrent.name);
this.chainCurrent = this.chainCurrent.next;
}
nameStr = nameArray.join(" ") + " "; //統一標准,末尾補一個空格
//依賴模塊去重
while(repeatRegex.exec(nameStr)){
nameStr = nameStr.replace(repeatRegex, function(g0, g1, g2){
return g0.substring(0, (g0.length - g2.length));
});
}
nameStr = nameStr.substring(0, (nameStr.length - 1)); //去掉補充的多余空格
//依賴模塊名稱轉換為模塊路徑
nameArray = nameStr.split(" ");
for(i = 0; i < nameArray.length; i++){
srcArray.push(this.srcCache[nameArray[i]]);
}
return srcArray;
},
/**
* 遞歸加載模塊
* @param modules 配置對象
* @param name 模塊名稱
*/
load: function(modules, name){
var node = {},
module = this.findModule.call(modules, "name", name),
i = 0;
//判斷模塊是否存在
if(!module){
throw Error("依賴模塊 " + name +" 未找到");
}
//構造模塊依賴鏈表
node.name = name;
// node.src = module.src;
this.srcCache[name] = module.src;
node.next = this.chainHead;
this.chainHead = node;
//遞歸依賴
if(module.require && module.require.length){
for(i = 0;i < module.require.length; i++){
this.load(modules, module.require[i]);
}
}
},
/**
* 根據指定屬性名稱和屬性值查找模塊
* @param name 屬性名稱
* @param value 屬性值
* @returns {*}
*/
findModule: function(name, value){
var array = this,
item = {},
i = 0;
//遍歷模塊
for(i = 0; i < array.length; i++){
item = array[i];
//獲取指定模塊
if(item && item[name] === value){
return item;
}
}
//找不到返回null
return null;
}
};
//暴露對外接口
return function(){
return logics.main.apply(logics, arguments);
};
}());
/**
* Test Usecase
* @type {*[]}
*/
var modules=[
{'name':'jquery','src':'/js/lib/jquery-1.8.3.js'},
{'name':'swfobject','src':'/js/utils/swfobject.js'},
{'name':'fancybox','src':'/js/jquery/jquery.fancybox.js','require':['jquery']},
{'name':'uploadify','src':'/js/utils/uploadify.js','require':['swfobject']},
{'name':'jqform','src':'/js/jquery/jquery.form.js','require':['jquery']},
{'name':'register','src':'/js/page/reg.js','require':['jqform']},
{'name':'login','src':'/js/page/login.js','require':['fancybox','jqform']},
{'name':'upload','src':'/js/page/upload.js','require':['fancybox','jqform','login','uploadify']}
];
console.log(loadModule(modules, "upload"));