首页 > 网站 > WEB开发 > 正文

根据配置文件加载js依赖模块(JavaScript面试题)

2024-04-27 14:16:20
字体:
来源:转载
供稿:网友

根据配置文件加载js依赖模块(javaScript面试题)

面试题目

根据下面的配置文件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加载两次吧!

小菜给出的这个解法,只是一个思路,肯定有比这更好的算法,小菜觉得可以用二叉树之类的算法解决,但小菜不会呀~~~

此算法没有考虑循环依赖的情景。

代码如下:

  1 /**  2  * 不考虑循环依赖  3  * @type {Function}  4  */  5 var loadModule = (function(){  6     /**  7      * 业务逻辑封装  8      * @type {{chainHead: {}, chainCurrent: {}, srcCache: {}, main: main, load: load, findModule: findModule}}  9      */ 10     var logics = { 11         chainHead: {},     //链表头 12         chainCurrent: {},  //链表当前节点 13         srcCache: {},      //module src 缓存 14         /** 15          * 对外接口 16          * @param modules  配置对象 17          * @param name  模块名称 18          * @returns {Array} 依赖模块列表,按照加载先后顺序排列 19          */ 20         main: function(modules, name){ 21             var nameArray = [],  //模块名称列表 22                 srcArray = [],   //依赖模块列表 23                 nameStr = "",    //模块名称字符串集 24                 repeatRegex = /(^| )([/w]+ ).*/2/,  //模块名称去重正则 25                 i = 0; 26  27             //粗略加载所有依赖模块 28             this.load(modules, name) 29  30             //构造模块名称字符串集 31             this.chainCurrent = this.chainHead; 32             while(this.chainCurrent.next){ 33                 nameArray.push(this.chainCurrent.name); 34                 this.chainCurrent = this.chainCurrent.next; 35             } 36             nameStr = nameArray.join(" ") + " ";  //统一标准,末尾补一个空格 37  38             //依赖模块去重 39             while(repeatRegex.exec(nameStr)){ 40                 nameStr = nameStr.replace(repeatRegex, function(g0, g1, g2){ 41                     return g0.substring(0, (g0.length - g2.length)); 42                 }); 43             } 44             nameStr = nameStr.substring(0, (nameStr.length - 1));  //去掉补充的多余空格 45  46             //依赖模块名称转换为模块路径 47             nameArray = nameStr.split(" "); 48             for(i = 0; i < nameArray.length; i++){ 49                 srcArray.push(this.srcCache[nameArray[i]]); 50             } 51  52             return srcArray; 53         }, 54         /** 55          * 递归加载模块 56          * @param modules  配置对象 57          * @param name  模块名称 58          */ 59         load: function(modules, name){ 60             var node = {}, 61                 module = this.findModule.call(modules, "name", name), 62                 i = 0; 63             //判断模块是否存在 64             if(!module){ 65                 throw Error("依赖模块 " + name +" 未找到"); 66             } 67             //构造模块依赖链表 68             node.name = name; 69 //            node.src = module.src; 70             this.srcCache[name] = module.src; 71             node.next = this.chainHead; 72             this.chainHead = node; 73             //递归依赖 74             if(module.require && module.require.length){ 75                 for(i = 0;i < module.require.length; i++){ 76                     this.load(modules, module.require[i]); 77                 } 78             } 79         }, 80         /** 81          * 根据指定属性名称和属性值查找模块 82          * @param name  属性名称 83          * @param value  属性值 84          * @returns {*} 85          */ 86         findModule: function(name, value){ 87             var array = this, 88                 item = {}, 89                 i = 0; 90             //遍历模块 91             for(i = 0; i < array.length; i++){ 92                 item = array[i]; 93                 //获取指定模块 94                 if(item && item[name] === value){ 95                     return item; 96                 } 97             } 98  99             //找不到返回null100             return null;101         }102     };103 104     //暴露对外接口105     return function(){106         return logics.main.apply(logics, arguments);107     };108 }());109 110 111 /**112  * Test Usecase113  * @type {*[]}114  */115 116 var modules=[117     {'name':'jquery','src':'/js/lib/jquery-1.8.3.js'},118     {'name':'swfobject','src':'/js/utils/swfobject.js'},119     {'name':'fancybox','src':'/js/jquery/jquery.fancybox.js','require':['jquery']},120     {'name':'uploadify','src':'/js/utils/uploadify.js','require':['swfobject']},121     {'name':'jqform','src':'/js/jquery/jquery.form.js','require':['jquery']},122     {'name':'register','src':'/js/page/reg.js','require':['jqform']},123     {'name':'login','src':'/js/page/login.js','require':['fancybox','jqform']},124     {'name':'upload','src':'/js/page/upload.js','require':['fancybox','jqform','login','uploadify']}125 ];126 127 console.log(loadModule(modules, "upload"));


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表