首先看下常规开发中javascript非结构化组织代码
function appInit () { //程序初始化操作 } function appModule1 () { //程序功能模块1 } function appModule2 () { //程序功能模块2 } function appModule3 () { //程序功能模块3 } $( document ).ready(appInit )
从技术角度看,这种代码方式并没有任何错误,但是通过下图可以发现这些函数都是建立在全局名称空间下
若在全局名称空间中创建很多变量很快会导致严重的问题、比如在全局名称空间中定义了名为i、_或$的变量。
如何改善呢?
1、使用一个单例创建一个应用程序名称空间
var myApp = { init : function () { //程序初始化操作 }, appModule1 : function () { //程序功能模块1 }, appModule2 : function () { //程序功能模块2 }, appModule3 : function () { //程序功能模块3 } } $( document ).ready(myApp.init)
对于上面的新结构,打开chrome查看window下的属性时仅看到单个变量myApp,这中方式极大的降低了变量名冲突的可能性。
这一模式允许多个开发人员跨越多个文件,在单个应用程序名称空间之下进行协同开发。从代码结构角度来说,可以将网站的每一部分拆成独立文件。比如本例中的common.js、
appModule1.js、appModule2.js和appModule3.js。每个开发人员都有一个自己负责的网站部分和相应的javascript文件,开发人员只需要关注自己的文件,不需要担心会发生冲突。
common.js var myApp = { common : { init : function () { //初始化应用程序通用代码 } } } appModule1.js myApp.appModule1 = { init : function () { //初始化代码 }, update : function () { //更新模块1的代码 }, render : function () { //呈现模块1的代码 } } appModule2.js myApp.appModule2 = { init : function () { //初始化代码 }, update : function () { //更新模块2的代码 }, render : function () { //呈现模块2的代码 } } appModule3.js myApp.appModule3 = { init : function () { //初始化代码 }, update : function () { //更新模块3的代码 }, render : function () { //呈现模块3的代码 } }
2、Module模式
模块模式是单例的一种变种,增强了单例模式提供的封装性,并增加了创建私有方法和私有属性的功能
模块模式包含三个主要组件:一个与前面例子类似的命名空间、一个立即执行函数和函数返回对象,该返回对象包含公有方法和公有属性,js代码如下:
//app的名称空间。传入jquery对象以缩短查找过程 var myApp = function( $ ){ //私有变量和方法 var message = " i am a module "; function multiplier (x,y) { return x * y; }; //返回对象包含公有属性和方法 return { init:function(){ //初始化app }, prop : '42', getProduct : function(){ //访问私有方法 return multiplier(2,3); }, shareMessage : function (arg){ //对私有属性进行限制访问 if(arg == "admin"){ return message; } else { throw new Error("No access"); } } } }(jQuery)
控制台中测试如下:
扩展该模式以增加更多的模块也非常简单。如下代码:
myApp.module1 = function($){ //私有变量和方法 var config = { "color":"red", "title":"module1", "width":"20px" }; return { init:function(){ //初始化module1 }, updateConfig : function(obj){ config.color = obj.color || config.color; config.title = obj.title || config.title; config.width = obj.width || config.width; }, render:function(){ var $module1 = $("#id"); $module1.text(config.title) .css({"width":config.width,"color":config.color}) } } }(jQuery)
该代码描述了一个module1模块,它包含一个私有配置对象和一个公共方法,该公有方法允许根据一组预定义条件获得对module1配置的访问,类似于java中private和public关键字的使用。在js开发中,并非所以时候都需要使用这种保护访问,但当我们需要实现这样功能时,使用模块模式是非常重要的。