zoukankan      html  css  js  c++  java
  • 根据配置文件加载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             //找不到返回null
    100             return null;
    101         }
    102     };
    103 
    104     //暴露对外接口
    105     return function(){
    106         return logics.main.apply(logics, arguments);
    107     };
    108 }());
    109 
    110 
    111 /**
    112  * Test Usecase
    113  * @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"));
  • 相关阅读:
    事件处理之二:点击事件监听器的五种写法 分类: H1_ANDROID 2013-09-11 10:32 4262人阅读 评论(1) 收藏
    如何解决安卓SDK无法下载Package的问题 分类: H1_ANDROID 2013-09-09 10:26 1199人阅读 评论(0) 收藏
    adb常用命令 分类: H1_ANDROID 2013-09-08 15:22 510人阅读 评论(0) 收藏
    用IBM WebSphere DataStage进行数据整合: 第 1 部分 分类: H2_ORACLE 2013-08-23 11:20 688人阅读 评论(0) 收藏
    三大主流ETL工具选型 分类: H2_ORACLE 2013-08-23 11:17 426人阅读 评论(0) 收藏
    ETL概述 分类: H2_ORACLE 2013-08-23 10:36 344人阅读 评论(0) 收藏
    POI操作Excel常用方法总结 分类: B1_JAVA 2013-08-23 10:01 349人阅读 评论(0) 收藏
    段的创建表user_segments 分类: H2_ORACLE 2013-08-10 11:13 714人阅读 评论(0) 收藏
    让android项目支持boost 支持c++11
    unity中全屏背景图缩放
  • 原文地址:https://www.cnblogs.com/iyangyuan/p/4119144.html
Copyright © 2011-2022 走看看