javascript模块模式原先是由yahoo的douglas crockford提出的,在yahoo的博文中有关于此模式的描述(http://yuiblog.com/blog/2007/06/12/module-pattern/),这种模式也应用到了yui组件开发中,最核心的理念是用javascript的”类”封装私有和公有的属性和方法。
这种模式是javascript实现中的一种最佳实践方式.能够清晰地表达javascript面向对象概念 。它不允许开发人员定义全局变量去”污染”全局对象。通过增强这种模式,可以提高web的性能,同时这种模式实现的javascript代码也是易于维护的。
在javascript程序设计语言中,函数可以作为一个模块,在某些情况下,需要创建的是单例对象,而不是创建一个类的实例。在模块的内部,公共接口可以访问模块中的私有变量以及私有方法。这些公共接口函数又叫做特权方法(privileged methods)
许多javascript实现的应用程序使用的都是单例,因此javascript模块模式应用得就比较多。因此,创建一个匿名函数用来返回一个字面量对象包装的特权方法集,由于闭包原则,这些特权方法有权访问到匿名函数中的变量已经方法,这就是模块模式。
为什么使用模块模式?
1. 通过此模式可以把面向对象的一些理念在javascript语言中表述得更清晰,比如封装的思想。
2. 通过特权方法可以访问到私有变量以及私有方法,因为你不希望这些私有变量以及方法被外部无限制地访问。
使用此模式时需要注意的就是闭包的实现,即返回的特权方法。
自执行函数
在模块模式中,通过自执行方法来创建全局单例对象,通常创建的单例对象都是全局的。自执行方法通常用来创建匿名函数的。看一个例子:
(function(){
//函数体的实现
})();
理解了上面的自执行函数后,下面看一下模块模式
var jsmodule = function(){//全局单例对象
var privatevar = "foo";
var privatemethod = function(){
return privatevar;
};
return {
printvar: function(){
return privatemethod();
}
};
}();//自执行函数
console.log(jsmodule.printvar());
也可以这样:
var jsmodule = function(){
var privatevar = "foo";
var privatemethod = function(){
return privatevar;
};
var obj ={//注意这里的字面量对象可以是通过工厂模式创建的对象
printvar: function(){
return privatemethod();
}
};
obj.appendbar = function(){//对返回的对象进行扩展。
return "bar";
}
return obj;
}();
console.log(jsmodule.printvar());//foo
console.log(jsmodule.appendbar());//bar
创建子模块
在原有模块基础上加强模块功能
var jsmodule = (function(){
var privatevar = "foo";
var privatemethod = function(){
return privatevar;
}
return {
printvar: function(){
return privatemethod();
}
}
})();
jsmodule.submodule = function(){//在现有模块基础上添加子模块,相当于给一个字面量对象添加一个属性,这个属性值还是一个字面量对象
var anotherprivatevar = "bar";
var sayword = function(str){
switch(str)
{
case "foo":
return "foo bar";
default:
return "hello world";
}
};
return {
say: function(){
return sayword(jsmodule.printvar());
}
}
}();
console.log(jsmodule.submodule.say());
扩展模块
通过把现有模块包装到一个新的模块来扩展现有模块。可以访问现有模块中的方法,以及重写现有模块方法:
var newjsmodule = function(super_module){
var parent_module = super_module;//下面就可以访问父模块特权方法了
parent_module.printvar = function(){//重写父模块方法
return "bar";
};
var privatemethod2 = function(){
return "hello javascript";
};
return {
newprintvar: function(){
return parent_module.printvar();//访问父模块方法
}
}
}(jsmodule);//通过传递已有模块来扩展该模块,定义完匿名函数就立刻执行
console.log(newjsmodule.newprintvar());
模块模式的缺点
如果想改变属性和方法的可见性,那么就要修改每一处使用到这些属性以及方法的地方
在模块后来添加的方法中无法访问到原模块中的私有属性以及方法,可以通过创建子模块或者扩展模块来扩展功能。
var jsmodule = function(){
var privatevar = "foo";
var privatemethod = function(){
return privatevar;
};
return {
printvar: function(){
return privatemethod();
}
};
}();
console.log(jsmodule.printvar());
jsmodule.newmethod = function(){
return privatemethod();referenceerror, privatemethod is not defined()
}
console.log(jsmodule.newmethod());
小结
没有完美的解决方案,只有合适的。通过对象模式可以写出大型复杂的javascript程序,yui的开发都用到此模式,所以在平时的开发中还是值得借鉴的。
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/