像C++一样写JavaScript

C/C++/Java的include或import可以引用第3方文件和包. 这个功能在Html/Js里没有默认的实现. 假设我们有这样一个HTML文件index.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1">
<title>欢迎使用ligerUI</title> <link href="lib/ligerUI/skins/Aqua/css/ligerui-all.css" rel="stylesheet" type="text/css" />
<link href="lib/ligerUI/skins/Gray/css/all.css" rel="stylesheet" type="text/css" />
<link href="lib/css/common.css" rel="stylesheet" type="text/css" />
<link href="lib/css/index.css" rel="stylesheet" type="text/css" /> <script src="lib/jquery/jquery-1.5.2.min.js" type="text/javascript"></script>
<script src="lib/ligerUI/js/ligerui.min.js" type="text/javascript"></script>
<script src="lib/ligerUI/js/plugins/ligerTab.js" type="text/javascript"></script>
<script src="lib/ligerUI/js/plugins/ligerLayout.js" type="text/javascript"></script> <script src="lib/js/common.js" type="text/javascript"></script>
<script src="lib/js/LG.js" type="text/javascript"></script>
<script src="lib/js/login.js" type="text/javascript"></script> <script src="/lib/jquery-validation/jquery.validate.min.js" type="text/javascript"></script>
<script src="/lib/jquery-validation/jquery.metadata.js" type="text/javascript"></script>
<script src="/lib/jquery-validation/messages_cn.js" type="text/javascript"></script> <script src="lib/js/changepassword.js" type="text/javascript"></script>
<script src="lib/ligerUI/js/plugins/ligerForm.js" type="text/javascript"></script> <!-- settings menus -->
<script src="index.html.js" type="text/javascript"></script>
</head>
<body>
...
</body>
</html>

可以看到, 为了使用某个第3方库(这里是ligerUI), 我们不得不把所有需要的js文件在html里引入进来. 下面修改上面的index.html, 看看新的写法可以给我们带来什么惊喜:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1">
<title>欢迎使用ligerUI</title> <link href="lib/ligerUI/skins/Aqua/css/ligerui-all.css" rel="stylesheet" type="text/css" />
<link href="lib/ligerUI/skins/Gray/css/all.css" rel="stylesheet" type="text/css" />
<link href="lib/css/common.css" rel="stylesheet" type="text/css" />
<link href="lib/css/index.css" rel="stylesheet" type="text/css" /> <script src="lib/prerequisite.js" type="text/javascript"></script>
<script src="index.html.js" type="text/javascript"></script>
</head>
<body>
...
</body>
</html>

是不是简洁多了, 这个写法的关键是我们必须在引用任何js之前引入一个全局的API文件, 这里是prerequisite.js, 然后就可以引入自己的js文件, 这里是index.html.js, 在自己的js文件里引入所有我们需要的第3方库文件(如ligerUI). 下面我们看看index.html.js这个文件里作了什么:

/**
* index.html.js
* version: 0.0.1
*/
UTIL.importScripts(
"lib/jquery/jquery-1.5.2.min.js",
"lib/ligerUI/js/ligerui.min.js",
"lib/js/common.js",
"lib/js/LG.js",
"lib/js/login.js",
"lib/jquery-validation/jquery.validate.min.js",
"lib/jquery-validation/jquery.metadata.js",
"lib/jquery-validation/messages_cn.js",
"lib/js/changepassword.js"
); /* 下面是业务代码, 和文件包含没关系 */
(function (window, undefined) {
"use strict"; /**
* public interfaces
*/ }(window));

是不是很神奇呢, 这个和C/C++/java很像啦. UTIL.importScripts(...) 这个函数帮我们做了一切事情, 它是在 prerequisite.js 中定义的, 那么最后就是prerequisite.js文件:

/**
* prerequisite.js
* included before all *.js
* version: 0.0.1
* cheungmine
* 2012-5
*/
(function (window, undefined) {
"use strict"; window.UTIL = {} /* Modify DEBUG = false if release */
var DEBUG = true; var log = function () {
if (window.UTIL.DEBUG === true) {
/* Thanks to Paul Irish for this one:
* http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
*/
log.history = log.history || [];
log.history.push(arguments); /* Make sure console is present */
if ('object' === typeof console) {
/* Setup console and arguments */
var c = console[console.warn? 'warn':'log'],
args = Array.prototype.slice.call(arguments),
a;
/* Add marker to first argument if it's a string */
if (typeof arguments[0] === 'string') {
/* args[0] = 'your marker: ' + args[0]; */
} /* Apply console.warn or .log if not supported */
a = c.apply? c.apply(console, args) : c(args);
}
}
}; var getScriptPath = function (jsfile) {
var e = {};
var htmlPath = "";
var jsPath = ""; if (document.location.protocol === 'file:'){
e.BasePath = unescape(document.location.pathname.substr(1));
e.BasePath = 'file://' + e.BasePath.substring(0,e.BasePath.lastIndexOf('/')+1);
e.FullBasePath = e.BasePath;
} else {
e.BasePath = document.location.pathname.substring(0,document.location.pathname.lastIndexOf('/')+1);
e.FullBasePath = document.location.protocol + '//' + document.location.host + e.BasePath;
} htmlPath = e.FullBasePath;
var i, at, src, slc, scriptTag = document.getElementsByTagName("script"); for (i = 0; i < scriptTag.length; i++) {
src = scriptTag[i].src;
at = src.lastIndexOf(jsfile); if (at!==-1) {
at++;
slc=src.toLowerCase();
if (slc.indexOf("file://") === 0) {
jsPath = src.substring(0,at);
break;
} else if (slc.indexOf("http://") === 0) {
jsPath = src.substring(0,at);
break;
} else if (slc.indexOf("https://") === 0) {
jsPath = src.substring(0,at);
break;
} else if (slc.indexOf("../") === 0) {
jsPath = htmlPath + src.substring(0,at);
break;
} else if (slc.indexOf("./") === 0) {
jsPath = htmlPath + src.substring(0,at);
break;
} else if (slc.indexOf("/") === 0) {
if (document.location.protocol === 'http:' || document.location.protocol === 'https:') {
jsPath = document.location.protocol + "//" + document.location.host + src.substring(0,at);
}
break;
} else if (slc.search(/^([a-z]{1}):/) >= 0) {
jsPath = src.substring(0,at);
break;
} else {
jsPath = htmlPath;
}
}
}
return jsPath;
}; var getScriptName = function () {
var js = document.scripts;
return js[js.length-1].src.substring(js[js.length-1].src.lastIndexOf("/"));
} var appendScript = function (url, source, head) {
if ( source && !document.getElementById(url) ) {
var oHead = head ? head : document.getElementsByTagName("HEAD").item(0);
var oScript = document.createElement("script");
oScript.language = "javascript";
oScript.type = "text/javascript";
oScript.id = url;
oScript.defer = true;
oScript.text = source;
oHead.appendChild(oScript);
}
} var importScripts = (function (globalEval) {
var oHead = document.getElementsByTagName("HEAD").item(0); var xhr = null;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if ( window.ActiveXObject ) {
try {
xhr = new ActiveXObject("MsXml2.XmlHttp");
} catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
if (! xhr) {
throw "prerequisite.js: XMLHttpRequest Not supported."
} var basePath = null; return function importScripts () {
var
args = Array.prototype.slice.call(arguments),
len = args.length,
i = 0,
meta,
data,
content
; if (!basePath) {
basePath = getScriptPath(getScriptName());
} for (; i<len; i++) {
var url = basePath + args[i]; if (url.substr(0, 5).toLowerCase() === "data:") {
data = url;
content = data.indexOf(",");
meta = data.substr(5,content).toLowerCase();
data = decodeURIComponent(data.substr(content+1)); if (/;\s*base64\s*[;,]/.test(meta)) {
data=atob(data);
} if (/;\s*charset=[uU][tT][fF]-?8\s*[;,]/.test(meta)) {
data = decodeURIComponent(escape(data));
}
} else {
xhr.open("GET", url, false /* async = false */);
xhr.send(null);
data = xhr.responseText;
} /* globalEval(data); */
appendScript(url, data, oHead);
}
};
} (eval)); /**
* global functions:
*/
window.UTIL.ERRINDEX = -1;
window.UTIL.DEBUG = DEBUG;
window.UTIL.log = log;
window.UTIL.importScripts = importScripts;
}(window));

最后我总结一下, 为了实现类似C/java的文件引用包含, 我写了一个prerequisite.js, 它提供全局的函数UTIL.importScripts(), prerequisite.js唯一的要求就是必须在页面的其他js加载前加载. 以后我们就可以在我们的js里使用UTIL.importScripts() 包含任何你想要包含的js文件. 因为我们必须要保证包含的文件必须被加载, 因此UTIL.importScripts()采用的是同步模式.

好了, 大胆的使用这个技巧吧, 你就可以实现真正的code behind. 总共就3步:

1) 写一个A.html, 并将prerequisite.js作为第一个引入的js文件;

2) 写自己的B.js库, 需要引用其他C.js, D.js, E.js文件的时候,就在B.js文件头部使用

UTIL.importScripts("/path/C.js", "/path/D.js", "/path/E.js");

3) path是C,D,E.js相对于B.js的路径.

像C++一样写JavaScript的更多相关文章

  1. CoffeeScript飞一样的写javascript

    之前看到同事在使用coffeescript写js,当我看到那简介的coffee文件,就深深的被coffescript吸引了,简洁的语法,熟练之后会大大提升javascript的开发速度,写脚本也能像飞 ...

  2. 使用Typescript来写javascript

    使用Typescript来写javascript 前几天尝试使用haxejs来写javascript,以获得静态类型带来的益处.虽然成功了,但很快发现将它与angularjs一起使用,有一些不太顺畅的 ...

  3. 代码规范(RL-TOC)用更合理的方式写 JavaScript

    代码可以改变世界 不规范代码可以毁掉世界 只有先学会写规范的代码,才可以走的更远 编程语言之间有很多编程规范都是通用: 命名 不要用语言不明的缩写,不用担心名字过长,名字一定要让别人知道确切的意思; ...

  4. 如何写javascript代码隐藏和显示这个div

    如何写javascript代码隐藏和显示这个div 浏览次数:82次悬赏分:10 | 解决时间:2011-4-21 14:41 | 提问者:hade_girl <div id="div ...

  5. 【blade04】用面向对象的方法写javascript坦克大战

    前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面 ...

  6. Asp.Net_ 服务端向客户端写JavaScript脚本

    在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArrayDe ...

  7. 用C#在Visual Studio写Javascript单元测试(Firefox内核)

    引用nuget包: 注意:Geckofx45 nuget包必须是最后引用,否则初始化会出错 编写JsRunner using Gecko; using System; using System.Col ...

  8. 用C#在Visual Studio写Javascript单元测试

    1.在vs创建一个标准的单元测试工程 2.引用nuget包:Edge.js 我是用的是6.11.2版本 3.编写JsRunner类 using EdgeJs; using System; using ...

  9. 2021 年写 JavaScript 代码的 17 个优化技巧

    我们经常会写一些 JavaScript 代码,但是如何写出干净又易维护的代码呢?本文将讲解 17 个 JavaScript 代码的技术帮助你提高编程水平,此外,本文可以帮助您为 2021 年的 Jav ...

随机推荐

  1. PPT2010小技巧 教你如何快捷抠图

    相信不少人在做PPT时,都有想插入个漂亮个性图案的想法,但是往往手头上的图片都不太令人满意,需要“裁剪”一下才能达不到自己想要的效果.这时大部分人可能会PS,但是相比起今天要分享给大家的方法,步骤就显 ...

  2. bzoj 4031: [HEOI2015]小Z的房间 轮廓线dp

    4031: [HEOI2015]小Z的房间 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 98  Solved: 29[Submit][Status] ...

  3. 【技术贴】破解Myeclipse10.7

    程序用的是http://www.cr173.com/soft/58306.html这个破解程序,是英文版的中文版.使用起来非常爽,看下面 使用期间关掉Myeclipse 期间的第三步,点击激活,此时会 ...

  4. Entity FrameWork知识点汇总

    这里罗列的并非EF的所有知识点 ,只是我在开发过程中遇到或者使用到的知识,记录于此, 备忘 1:EF的三种创建方式 A:Database First B:Model First C:Code Firs ...

  5. Mongodb数据更新命令

    一.Mongodb数据更新命令 Mongodb更新有两个命令:update.save. 1.1update命令 update命令格式: db.collection.update(criteria,ob ...

  6. 批量建立EXCHANGE邮件帐号建立三部曲

    第一步:从AD里导出用户名(可以基于OU),将输出的CSV的DN列删除,并去除可能的测试及其它用途用户名. csvde -f users-gz.csv -d "ou=MKT gz,dc=xm ...

  7. 【网络流24题】No.9 方格取数问题 (二分图点权最大独立集)

    [题意] 在一个有 m*n 个方格的棋盘中, 每个方格中有一个正整数. 现要从方格中取数, 使任意 2 个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入文件示例inp ...

  8. Class类文件结构、类加载机制以及字节码执行

    一.Class类文件结构 Class类文件严格按照顺序紧凑的排列,由无符号数和表构成,表是由多个无符号数或其他数据项构成的符合数据结构. Class类文件格式按如下顺序排列:   类型 名称 数量 u ...

  9. 【Xamarin挖墙脚系列:多窗口之间的导航】

    原文:[Xamarin挖墙脚系列:多窗口之间的导航] 在Android中:Intent对象,通知松散耦合的Activity等组件 在IOS中:Segue对象连接视图 <button opaque ...

  10. bzoj1237

    假如不存在相等的两个数不能配对,那很容易贪心得到,A中rank 1匹配B中rank 1 A中rank2 匹配B中rank 2…… 有了相等不能匹配这个条件,那么A中rank i可能和rank i,i- ...