js中实现js文件的导入

 

Javascript不比Java,没有import关键字(据说Javascript2.0将加入Import和命名空间)。在网上查了很多别人写的Import函数的代码,通常都是直接在HTML里插入script元素来实现。这种方式无法实现同步导入,即import函数调用的下面无法马上使用导入JS里面的变量。

下面的代码将使用AJAX方式来实现Import功能,可以实现同步导入。调用方式很简单,在JS代码开始处调用$import()函数就可以了。

 

另外本代码还集成了CSS的导入,虽然很简单但也很有用。因为如果你编写了一个JS文件来实现某种控件,你肯定不希望使用你的JS文件的人还要在他自己的代码里引入你的CSS文件。所以你可以使用本代码里的$import函数在你的JS文件中引用你的CSS文件。

 

最后,本代码还提供了一个很振奋的功能,即为你导入的JS文件中的全局变量加上命名前缀。我们在很多高级语言中都可以做到这一点,如引用JAVA的JSP标签库,<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>,这个库里面的内容可以用前缀C与其他标签库区分开来。本代码也提供了类似的功能,如:$import("../lib/head.js","h")。之后就可以用h.XXX来引用head.js里定义的函数和变量了。

 

代码如下:

[javascript] view plain copy print ?
  1. /** 
  2.  * 这个JS文件提供了命名空间、JS文件导入功能。 注:import本身是个关键字,不能用来做变量函数名 
  3.  * 通过本代码可以导入Javascript文件,可以使用绝对URL和相对URL作为路径 $import("../lib/head.js"); 
  4.  * $import("head.js"); 可以导入CSS文件 $import("head.css"); 
  5.  * 导入Javascript文件时,可以为导入文件里所定义的全局变量增加前缀,如: $import("prototype.js","p"); var 
  6.  * mydiv = p.$("myDiv"); 
  7.  * 但只有用var定义的全局变量和全局函数将增加前缀,而没有用var定义的变量将被视为必须要为全局的变量,不增加前缀 
  8.  *  
  9.  * @author 由月 
  10.  */  
  11. var Import = {};  
  12.   
  13. Import.importedJSFiles = [];  
  14. Import.importingJSFiles = [];  
  15. Import.importedCSSFiles = [];  
  16.   
  17. Import.$import = function(url, prefix) {  
  18.     // 检查参数合法   
  19.     if (url == null || url == "")  
  20.         return;  
  21.     // 获取导入文件的完整URL   
  22.     var fullUrl = Import.getFullPathFromUrl(url);  
  23.     // 先将此URL放入正在导入的列表中   
  24.     Import.addImportingFile(fullUrl);  
  25.     // 判断导入的是JS文件还是CSS文件   
  26.     if(Import.getFileType(fullUrl) == ".js"){  
  27.         Import.importJS(fullUrl, prefix);  
  28.     } else {  
  29.         Import.importCSS(fullUrl);  
  30.     }  
  31.     // 将URL从正在导入列表中移除,并加入已导入列表   
  32.     Import.addImportedFile(fullUrl);  
  33. };  
  34. Import.importCSS = function(url) {  
  35.     // 检查此文件是否已经被导入过   
  36.     if (Import.isImported(url))  
  37.         return;  
  38.     var head = document.getElementsByTagName("head")[0];  
  39.     // IE6 cannot support appendchild for head when BASE tag is present.   
  40.     // So we have to use document.write as instead.   
  41.     // We need better solution for this IE bug.   
  42.     // var link = head.appendChild(document.createElement("link"));   
  43.     var link = document.createElement("link");  
  44.     link.href = url;  
  45.     link.type = "text/css";  
  46.     link.rel = "stylesheet";  
  47.     if (document.readyState == "complete") {  
  48.         // if this method is called after the page loaded, for example,   
  49.         // in a script with defer tag, then use appendChild,   
  50.         // otherwise the document will be cleared when invoking   
  51.         // document.write.   
  52.         head.appendChild(link);  
  53.     } else {  
  54.         document.write(link.outerHTML);  
  55.     }  
  56.   
  57. };  
  58. Import.importJS = function(url, prefix) {  
  59.     // 检查此文件是否已经被导入过   
  60.     if (Import.isImported(url))  
  61.         return;  
  62.     // 通过AJAX获取文件内容   
  63.     // alert(url);   
  64.     var script = Import.getScriptContent(url);  
  65.     // alert(script);   
  66.     // 加上命名空间并执行脚本   
  67.     Import.execute(script, prefix);  
  68. };  
  69. Import.execute = function(script, prefix) {  
  70.     if (prefix != null && prefix != "") {  
  71.         var variables = Import.analysScript(script); // 分析出脚本中所有的全局变量   
  72.         if (variables.length > 0) {  
  73.             var pre = eval(prefix + " = {};"); // 根据prefix生成对象   
  74.             for ( var i = 0; i < variables.length; i++) {  
  75.                 var variable = variables[i];  
  76.                 // alert(variable);   
  77.                 pre[variable] = null;  
  78.             }  
  79.             var extendScript = "; var pre="  
  80.                     + prefix  
  81.                     + ";for(var attr in pre){try{pre[attr]=eval(attr);}catch(e){}}";  
  82.             var wholeScript = "(function(){" + script + extendScript + "})();";  
  83.             window.execScript(wholeScript);  
  84.         }  
  85.     } else {  
  86.         window.execScript(script);  
  87.     }  
  88. };  
  89. Import.analysScript = function(script) {  
  90.     // 检查参数   
  91.     if (script == null || script == "")  
  92.         return null;  
  93.   
  94.     var globalVariables = null;  
  95.     // 定义词法状态机   
  96.     var wordStateMachine = {  
  97.         currentState : "init"// 状态机的当前状态   
  98.         wordCache : [], // 保存用来构造单词的缓存   
  99.         stateObj : {}, // 保存状态间变量   
  100.         getStateObj : function(state) {  
  101.             if (state && state != "") {  
  102.                 if (this.stateObj[state] == null)  
  103.                     this.stateObj[state] = {};  
  104.                 return this.stateObj[state];  
  105.             }  
  106.             return null;  
  107.         },  
  108.         process : function(script) {  
  109.             var self = this;  
  110.             var index = 0;  
  111.             var outputWords = [];  
  112.             while (index < script.length) {  
  113.                 var c = script.charAt(index);  
  114.                 var result = "self";  
  115.                 var word = self.wordCache.join("");  
  116.                 while (result == "self") { // 继续在当前字符上调用handler   
  117.                     result = self.handlers[self.currentState](c);  
  118.                 }  
  119.                 if (result == "complete") { // 完成了一个单词的分析   
  120.                     // alert(word);   
  121.                     var output = grammarStateMachine.process(word);  
  122.                     if (output != null) {  
  123.                         // alert("output:" + output);   
  124.                         outputWords[outputWords.length] = output;  
  125.                     }  
  126.                 } else if (result == "next") { // 读取下一个字符   
  127.                     self.wordCache[self.wordCache.length] = c;  
  128.                     index++;  
  129.                 }  
  130.             }  
  131.             return outputWords;  
  132.         },  
  133.         handlers : {  
  134.             "init" : function(char) {  
  135.                 wordStateMachine.wordCache = [];  
  136.                 if ("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"  
  137.                         .indexOf(char) >= 0) {  
  138.                     // if(char == "$")alert(char);   
  139.                     wordStateMachine.currentState = "identify_start";  
  140.                 } else if ("{}()".indexOf(char) >= 0) {  
  141.                     wordStateMachine.currentState = "block_start";  
  142.                     return "self";  
  143.                     /* 
  144.                      * } else if ("/"'".indexOf(char) >= 0) { // 
  145.                      * 暂时取消字符串分析,因为不好处理正则表达式中的'和" wordStateMachine.currentState = 
  146.                      * "quote_start"; 
  147.                      * wordStateMachine.getStateObj("quote_start").quote = char; 
  148.                      * return "next"; 
  149.                      */  
  150.                 } else if (char == "/") {  
  151.                     wordStateMachine.currentState = "comment";  
  152.                     return "next";  
  153.                 }  
  154.                 return "next";  
  155.             },  
  156.             "identify_start" : function(char) { // 进入标识符分析   
  157.                 var result = "self";  
  158.                 if ("$abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_"  
  159.                         .indexOf(char) >= 0) {  
  160.                     result = "next";  
  161.                 } else if ("".indexOf(char) >= 0) {  
  162.   
  163.                 } else {  
  164.                     wordStateMachine.currentState = "identify_finish";  
  165.                     result = "self";  
  166.                 }  
  167.                 return result;  
  168.             },  
  169.             "identify_finish" : function(char) { // 标识符分析完成   
  170.                 var result = "complete";  
  171.                 wordStateMachine.currentState = "init";  
  172.                 return result;  
  173.             },  
  174.             "block_start" : function(char) { // 分析括号和代码块   
  175.                 wordStateMachine.currentState = "block_finish";  
  176.                 return "next";  
  177.             },  
  178.             "block_finish" : function(char) {  
  179.                 wordStateMachine.currentState = "init";  
  180.                 return "complete";  
  181.             },  
  182.             "quote_start" : function(char) { // 分析引号   
  183.                 // alert(char + "," + wordStateMachine.wordCache.join(""));   
  184.                 var finish = false;  
  185.                 if (char == wordStateMachine.getStateObj("quote_start").quote) {  
  186.                     for ( var i = wordStateMachine.wordCache.length - 1; i >= 0; i = i + 2) {  
  187.                         var a = wordStateMachine.wordCache[i];  
  188.                         var b = wordStateMachine.wordCache[i - 1];  
  189.                         if (a != "//") {  
  190.                             finish = true;  
  191.                             break;  
  192.                         } else if (b != "//") {  
  193.                             finish = false;  
  194.                             break;  
  195.                         }  
  196.                     }  
  197.                     if (finish) {  
  198.                         wordStateMachine.currentState = "quote_finish";  
  199.                         return "self";  
  200.                     }  
  201.                 }  
  202.                 return "next";  
  203.             },  
  204.             "quote_finish" : function(char) {  
  205.                 alert(char + "," + wordStateMachine.wordCache.join(""));  
  206.                 wordStateMachine.currentState = "init";  
  207.                 return "next";  
  208.             },  
  209.             "comment" : function(char) { // 分析注释   
  210.                 if (char == "/") {  
  211.                     wordStateMachine.currentState = "comment_start";  
  212.                     wordStateMachine.getStateObj("comment").comment = "line";  
  213.                 } else if (char == "*") {  
  214.                     wordStateMachine.currentState = "comment_start";  
  215.                     wordStateMachine.getStateObj("comment").comment = "block";  
  216.                 } else {  
  217.                     wordStateMachine.currentState = "regex";  
  218.                 }  
  219.                 return "self";  
  220.             },  
  221.             "comment_start" : function(char) {  
  222.                 // alert(char+","+wordStateMachine.wordCache.join(""));   
  223.                 if (wordStateMachine.getStateObj("comment").comment == "line"  
  224.                         && char == "/n") {  
  225.                     wordStateMachine.currentState = "comment_finish";  
  226.                 } else if (wordStateMachine.getStateObj("comment").comment == "block"  
  227.                         && char == "/"  
  228.                         && wordStateMachine.wordCache[wordStateMachine.wordCache.length - 1] != "//") {  
  229.                     wordStateMachine.currentState = "comment_finish";  
  230.                 }  
  231.                 return "next";  
  232.             },  
  233.             "comment_finish" : function(char) {  
  234.                 wordStateMachine.currentState = "init";  
  235.                 return "next";  
  236.             },  
  237.             "regex" : function(char) {  
  238.                 // TODO: 需要实现表达式分析才能分析出正则表达式   
  239.             wordStateMachine.currentState = "init";  
  240.             return "next";  
  241.         }  
  242.         }  
  243.     };  
  244.     // 定义语义状态机   
  245.     var grammarStateMachine = {  
  246.         currentState : "init",  
  247.         output : null,  
  248.         stateObj : {},  
  249.         getStateObj : function(state) {  
  250.             if (state && state != "") {  
  251.                 if (this.stateObj[state] == null)  
  252.                     this.stateObj[state] = {};  
  253.                 return this.stateObj[state];  
  254.             }  
  255.             return null;  
  256.         },  
  257.         process : function(word) {  
  258.             var self = this;  
  259.             var result = "self";  
  260.             var ret = null;  
  261.             while (result == "self") {  
  262.                 result = self.handlers[self.currentState](word);  
  263.             }  
  264.             if (result == "next") {  
  265.             } else if (result == "complete") {  
  266.                 ret = self.output;  
  267.                 self.output = null;  
  268.             }  
  269.             return ret;  
  270.         },  
  271.         handlers : {  
  272.             "init" : function(word) {  
  273.                 // alert("init:"+word);   
  274.                 if (word == "var") {  
  275.                     grammarStateMachine.currentState = "variable_define";  
  276.                 } else if (word == "function") {  
  277.                     grammarStateMachine.currentState = "function_define";  
  278.                 } else if (word == "{") {  
  279.                     grammarStateMachine.currentState = "block";  
  280.                     grammarStateMachine.getStateObj("block").blockLevel = 0;  
  281.                     return "self";  
  282.                 }  
  283.                 return "next";  
  284.             },  
  285.             "block" : function(word) {  
  286.                 var stateObj = grammarStateMachine.getStateObj("block");  
  287.                 if (word == "{") {  
  288.                     stateObj.blockLevel++;  
  289.                 } else if (word == "}") {  
  290.                     stateObj.blockLevel--;  
  291.                     if (stateObj.blockLevel == 0) {  
  292.                         grammarStateMachine.currentState = "init";  
  293.                     } else if (stateObj.blockLevel < 0) {  
  294.                         throw new Error("block unmatch");  
  295.                     }  
  296.                 }  
  297.                 return "next";  
  298.             },  
  299.             "variable_define" : function(word) {  
  300.                 grammarStateMachine.output = word;  
  301.                 grammarStateMachine.currentState = "variable_finish";  
  302.                 return "self";  
  303.             },  
  304.             "variable_finish" : function(word) {  
  305.                 grammarStateMachine.currentState = "init";  
  306.                 return "complete";  
  307.             },  
  308.             "function_define" : function(word) {  
  309.                 if (word == "(") {  
  310.                     grammarStateMachine.currentState = "function_arg_block";  
  311.                     return "self";  
  312.                 } else {  
  313.                     grammarStateMachine.output = word;  
  314.                     grammarStateMachine.currentState = "function_arg_block";  
  315.                 }  
  316.                 return "next";  
  317.             },  
  318.             "function_arg_block" : function(word) {  
  319.                 if (word == "(") {  
  320.                 } else if (word == ")") {  
  321.                     grammarStateMachine.currentState = "function_search_body";  
  322.                 }  
  323.                 return "next";  
  324.             },  
  325.             "function_search_body" : function(word) {  
  326.                 if (word == "{") {  
  327.                     grammarStateMachine.currentState = "function_start";  
  328.                     grammarStateMachine.getStateObj("function_start").blockLevel = 0;  
  329.                     return "self";  
  330.                 }  
  331.                 return "next";  
  332.             },  
  333.             "function_start" : function(word) {  
  334.                 var stateObj = grammarStateMachine  
  335.                         .getStateObj("function_start");  
  336.                 if (word == "{") {  
  337.                     stateObj.blockLevel++;  
  338.                 } else if (word == "}") {  
  339.                     stateObj.blockLevel--;  
  340.                     if (stateObj.blockLevel == 0) {  
  341.                         grammarStateMachine.currentState = "function_finish";  
  342.                         return "self";  
  343.                     }  
  344.                 }  
  345.                 return "next";  
  346.             },  
  347.             "function_finish" : function(word) {  
  348.                 // alert("function_finish:"+word)   
  349.             grammarStateMachine.currentState = "init";  
  350.             return "complete";  
  351.         }  
  352.         }  
  353.     };  
  354.     // 进入自动状态机   
  355.     globalVariables = wordStateMachine.process(script);  
  356.     return globalVariables;  
  357. };  
  358. Import.getScriptContent = function(url) {  
  359.     var req = new ActiveXObject("Microsoft.XmlHttp");  
  360.     var res;  
  361.     req.open("GET", url, false);  
  362.     req.send();  
  363.     if (req.status != 404) {  
  364.         if (req.readystate == 4) {  
  365.             res = req.responseText;  
  366.         }  
  367.     }  
  368.     return res;  
  369. };  
  370. Import.getFileType = function(url){  
  371.     url = url.split("?")[0];  
  372.     type = url.substring(url.length - 3);  
  373.     if(type.indexOf(".")==0){  
  374.         return type;  
  375.     }else{  
  376.         return "";  
  377.     }  
  378. }  
  379. /** 
  380.  * 记录下导入的文件 
  381.  */  
  382. Import.addImportingFile = function(url) {  
  383.     if (!Import.isImported(url)) {  
  384.         if(Import.getFileType(url) == ".js")  
  385.             Import.importingJSFiles.push(url);  
  386.         else  
  387.             Import.importingCSSFiles.push(url);  
  388.     }  
  389. };  
  390. Import.addImportedFile = function(url) {  
  391.     if (!Import.isImported(url)) {  
  392.         if(Import.getFileType(url) == ".js"){  
  393.             if(Import.importingJSFiles[Import.importingJSFiles.length - 1] == url){  
  394.                 Import.importingJSFiles.pop();  
  395.                 Import.importedJSFiles.push(url);  
  396.             }  
  397.         }else{  
  398.             Import.importedCSSFiles.push(url);  
  399.         }  
  400.     }  
  401. };  
  402. /** 
  403.  * 检查文件是否已经被导入过了 
  404.  */  
  405. Import.isImported = function(url) {  
  406.     if(Import.getFileType(url) == ".js"){  
  407.         for ( var i = 0; i < Import.importedJSFiles.length; i++) {  
  408.             if (Import.importedJSFiles[i] == url) {  
  409.                 return true;  
  410.             }  
  411.         }  
  412.     } else {  
  413.         for ( var i = 0; i < Import.importedCSSFiles.length; i++) {  
  414.             if (Import.importedCSSFiles[i] == url) {  
  415.                 return true;  
  416.             }  
  417.         }  
  418.     }  
  419.     return false;  
  420. };  
  421. /** 
  422.  * 获取导入文件的完整URL,包括HTTP头 
  423.  */  
  424. Import.getFullPathFromUrl = function(url) {  
  425.     var path = null;  
  426.     if (url.substr(0, 7).toLowerCase() == "http://") {  
  427.         // url为完整的URL地址   
  428.         path = url;  
  429.     } else if (url.substr(0, 1) == "/") {  
  430.         // url以/开头,为以站点根目录开始的路径   
  431.         path = "http://" + document.location.host + url;  
  432.     } else {  
  433.         var parentPage = document.location.href;  
  434.         var parentPath = parentPage.split("?")[0];  
  435.         parentPath = parentPath.substring(0, parentPath.lastIndexOf("/") + 1);  
  436.         var currentScriptPath = Import.getCurrentScriptPath();  
  437.         currentScriptPath = currentScriptPath.split("?")[0];  
  438.         if (currentScriptPath.toLowerCase().indexOf("http://") == 0) {  
  439.             // 当前脚本路径是以http开头   
  440.             path = currentScriptPath + url;  
  441.         } else {  
  442.             // 否则当前脚本路径为相对路径   
  443.             // 查看是否有BASE标签   
  444.             var base = document.getElementsByTagName("base")[0];  
  445.             if (base) {  
  446.                 var baseUrl = base.href;  
  447.                 path = baseUrl + currentScriptPath + url;  
  448.             } else {  
  449.                 path = parentPath + currentScriptPath + url;  
  450.             }  
  451.         }  
  452.         path = Import.toAbsolutePath(path);  
  453.     }  
  454.     return path;  
  455. };  
  456.   
  457. Import.toAbsolutePath = function(url) { // 转换为绝对URL   
  458.     var http = "http://";  
  459.     if (url.toLowerCase().indexOf("http://") == 0) {  
  460.         url = url.substring(7, url.length);  
  461.     }  
  462.     var path = url.split("?")[0];  
  463.     var queryString = (url.split("?").length > 1) ? "?" + url.split("?")[1] : "";  
  464.     dt = path.split("/");  
  465.     var newdt = [];  
  466.     for ( var i = 0; i < dt.length; i++) {  
  467.         var u = dt[i];  
  468.         if (u == "..") {  
  469.             newdt.pop();  
  470.         } else {  
  471.             newdt.push(u);  
  472.         }  
  473.     }  
  474.     return http + newdt.join("/") + queryString;  
  475. };  
  476.   
  477. /** 
  478.  * 获取当前运行的脚本文件的路径,路径不包括自身的文件名 
  479.  *  
  480.  * @return 
  481.  */  
  482. Import.getCurrentScriptPath = function() {  
  483.     var js = Import.importingJSFiles;  
  484.     if (js && js.length > 0) {  
  485.         js = js[js.length - 1];  
  486.         js = js.split("?")[0];  
  487.         js = js.substring(0, js.lastIndexOf("/") + 1);  
  488.     } else {  
  489.         js = document.scripts;  
  490.         var src = js[js.length - 1].src;  
  491.         src = src.split("?")[0];  
  492.         js = src.substring(0, src.lastIndexOf("/") + 1);  
  493.     }  
  494.     return js;  
  495. };  
  496. /** 
  497.  * ImportFile类 
  498.  *  
  499.  * @param path 
  500.  * @return 
  501.  */  
  502. Import.ImportFile = function(path) {  
  503.     this.path = path;  
  504.     this.fullPath = null;  
  505.     this.type = null;  
  506. };  
  507.   
  508. (function() {  
  509.     if (typeof $import == "undefined") {  
  510.         $import = Import.$import;  
  511.     }  
  512. })();  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值