创建模块的第一条规则:避免定义全局变量
要为模块提供载入标记,而这个标记在全局名字空间中最好只载入一次。
在使用名字空间的添加标示的时候,通常以文件的路径作为标示。
下面时根据域名创建名字空间的代码
var com;
if(!com)com={};
else if(typeof com!="object") throw new Error("com is already exists and is not an object");
if(!com.davidflanagan)com.davidflanagan={}
else if(typeof com.davidflanagan!="object") throw new Error("com.davidflanagan ia already exists and is not an object");
if(com.davidflanagan.Class)throw new Error("com.davidflanagan.Class already exists");
com.davidflanagan.Class={
define:function(data){/* add define here*/}
provides:function(o,c){/* add the code that can supply ablity*/}
}
测试一个模块的可用性
var com;
if(!com||!com.davidflanagan||!com.davidflanagan.Class)throw new Error("com/davidflanagan/Class.js has not been loaded");
以类作为模块
var com;
if(!com||!com.davidflanagan||!com.davidflanagan.Class)throw new Error("com/davidflanagan/Class.js has not been loaded");
com.davidflanagan.Complex=com.davidflanagan.Class.define({
name:"Complex",
construct:function(x,y){this.x=x;this.y=y;},
methods:{
add:function(c){
return new com.davidflanagan.Complex(this.x+c.x,this.y+c.y);
}
},
});
模块的初始化
以匿名函数的方式载入模块
从名字空间导入标记
使用名字空间来防止冲突,这是模块开发者的责任。从模块的命名空间把标记导入全局命名空间是用户的特权。对模块开发者来说,要记住,如果模块定义了引用基本类型值的属性,应该提供可以导入的accessor方法。
调用模块中的其他函数,必须使用他们的全名称限定。
私有标记的命名设定为前面加 下划线
闭包作为私有名字空间和作用域
这样可以将私有的变量和处理锁定到模块中。
模块工具的代码:
// 包含和模块相关工具的一个模块
var Module;//创建命名空间,也就是模块的名字,引用名
if(Module&&(typeof Module!="object"||Module.NAME))throw new Error("Name space 'Module' already exists");
//判断名字空间是否存在,并作出处理
Module={}//创建Module命名空间
//命名空间的信息
Module.NAME='Module';
Module.VERSION=0.1;
//引入遵循的方式
Module.EXPORT=["require","importSymbols"];
//对外面提供的可用属性或者方法
Module.EXPORT_OK=["createNamespace","isDefined","registerInitializationFunction","runInitializationFunctions", "modules","globalNamespace"];
Module.globalNamespace=this; //引入全局命名空间
Module.modules={"Module":Module}; //模块在命名空间中的存在形式,键值对的方式
//创建命名空间
Module.createNamespace=function(name,version){
if(!name)throw new Error("Module createNamespace():name required");//检测模块的名字是否存在
if(name.charAt(0)=="."||name.charAt(name.length-1)=="."||name.indexOf("..")!=-1){//检测name的格式是否正确
throw new Error("Module createNameapace(): illegal name :"+name);
}
var parts=name.split(".");//分割name成为字符串数组
var container=Module.globalNamespace;
for(var i=0;i<parts.length;i++){
var part=parts[i];
if(!container[part])container[part]={};
else if(typeof container[part]!="object"){
var n=parts.slice(0,i).join(".");
throw new Error(n+" already exists and is not an object");
}
container=container[part];
}
var namespace=conatiner;
if(namespace.Name)throw new Error("Module "+name+" is already defined");
namespace.NAME=name;
if(version)namespace.VERSION=version;
Module.modules[name]=namespace;
return namespace;
};
//确认是否存在与命名空间中
Module.isDefined=function(name){
return name in Module.modules;
};
//导入时检查名称和版本
Module.require=function(name,version){
if(!(name in Module.modules)){
throw new Error("Module "+name+" is not defined");
}
if(!version)return;
var n=Module.modules[name];
if(!n.VERSION||n.VERSION<version){
throw new Error("Module "+name+" has version "+n.version+" but version "+version+ " or greater is
required");
};
};
//导入标记
Module.importSymbols=function(from){
if(typeof from=="string")from=Module.modules[from];
if(!from||typeof from!="object")throw new Error("Module.importSymbols(): namespace object required");
var to=Module.globalNamespace;
var symbols=[];
var firstsymbol=1;
if(arguments.length>1 && typeof arguments[1]=="object" ){
if(arguments[1]!=null)to=arguments[1];
firstsymbol=2;
}
for(var a=firstsymbol;a<arguments.length;a++)symbols.push(arguments[a]);
if(symbols.length==0){
if(from.EXPORT){
for(var i=0;i<from.EXPORT.length;i++){
var s=from.EXPORT[i];
to[s]=from[s];
}
return;
}
}
var allowed;
if(from.EXPORT||from.EXPORT_OK){
allowed={};
if(from.EXPORT)for(var i=0;i<from.EXPORT.length;i++)allowed[from.EXPORT[i]]=true;
if(from.EXPORT_OK)for(var i=0;i<from.EXPORT_OK.length;i++)allowed[from.EXPORT_OK[i]]=true;
}
for(var i=0;i<symbols.length;i++){
var s=symbols[i];
if(!(s in from))throw new Error("Module.imortSymbols():symbol "+s+" is not defined");
if(allowed&&!(s in allowed)){
throw new Error("Module.importSymbols(): symbol "+s+" is not public and can not be imported");
};
to[s]=from[s];
}
};
//注册初始化函数
Module.registerInitializationFunction=function(f){
Module._initfuncs.push(f);
Module._registerEventHandler();
};
//运行初始化函数
Module.runInitializtionFunctions=function(){
for(var i=0;i<Module._initfuncs.length;i++){
try{Module._initfuncs[i]();}
catch(e){ /*add error process code */}
}
Module._initfuncs.length=0;
}
//初始化函数数组
Module._initfuncs=[];
//注册监听
Module._registerEventHandler=function(){
var clientside="window" in Module.globalNamespace&&"navigator" in window;
if(clientside){
if(window.addEventListener){
window.addEventListener("load",Module.runInitializationFunctions,false);
}
else if(window.attachEvent){
window.attachEvent("onload",Module.runInitializationFunctions);
}
else{
window.onload=Module.runInitializationFunctions;
}
}
Module._registerEventHandler=function(){};
};
本文介绍了一种有效的模块化编程方法,包括如何避免全局变量污染、使用命名空间防止冲突、通过闭包实现私有变量及函数,同时提供了实用的模块工具代码。
2043

被折叠的 条评论
为什么被折叠?



