您好,欢迎访问一九零五行业门户网

JavaScript架构设计Module模式用法实例详解

module模式是一个比较流行的设计模式,它可以通过大括号封装私有的变量,方法,状态的,通过包装这些内容,一般全局的对象不能直接访问,在这个设计模式里,只返回一个api,其它的内容全部被封装成私有的了。
另外,这个模式和自执行的函数表达式比较相似,唯一的不同是module返回的是对象,而自执行函数表达式返回的是function。
众所周知, javascript不想其它语言一样有访问修饰符,不能为每个字段或者方法声明private,public修饰符,那这个模式我们是如何实现的呢?那就是return一个对象,里面包括一些公开的方法,这些方法有能力去调用内部的对象。
看一下,下面的代码,这段代码是一个自执行代码,声明里包括了一个全局的对象basketmodule, basket数组是一个私有的,所以你的整个程序是不能访问这个私有数组的,同时我们return了一个对象,其内包含了3个方法(例如additem,getitemcount,gettotal),这3个方法可以访问私有的basket数组。
var basketmodule = (function() { var basket = []; //private return { //exposed to public additem: function(values) { basket.push(values); }, getitemcount: function() { return basket.length; }, gettotal: function(){ var q = this.getitemcount(),p=0; while(q--){ p+= basket[q].price; } return p; }  } }());
同时注意,我们return的对象直接赋值给了basketmodule,所以我们可以像下面一样使用:
//basketmodule is an object with properties which can also be methods basketmodule.additem({item:'bread',price:0.5}); basketmodule.additem({item:'butter',price:0.3}); console.log(basketmodule.getitemcount()); console.log(basketmodule.gettotal()); //however, the following will not work: console.log(basketmodule.basket);// (undefined as not inside the returned object) console.log(basket); //(only exists within the scope of the closure)
那在各个流行的类库(如dojo, jquery)里是如何来做呢?
dojo
dojo试图使用dojo.declare来提供class风格的声明方式,我们可以利用它来实现module模式,例如如果你想再store命名空间下声明basket对象,那么可以这么做:
//traditional way var store = window.store || {}; store.basket = store.basket || {}; //using dojo.setobject dojo.setobject("store.basket.object", (function() { var basket = []; function privatemethod() { console.log(basket); } return { publicmethod: function(){ privatemethod(); }  }; }()));
结合dojo.provide一起来使用,非常强大。
yui
下面的代码是yui原始的实现方式:
yahoo.store.basket = function () { //"private" variables: var myprivatevar = "i can be accessed only within yahoo.store.basket ."; //"private" method: var myprivatemethod = function () { yahoo.log("i can be accessed only from within yahoo.store.basket"); } return { mypublicproperty: "i'm a public property.", mypublicmethod: function () { yahoo.log("i'm a public method."); //within basket, i can access "private" vars and methods: yahoo.log(myprivatevar); yahoo.log(myprivatemethod()); //the native scope of mypublicmethod is store so we can //access public members using "this": yahoo.log(this.mypublicproperty); } }; } ();
jquery
jquery里有很多module模式的实现,我们来看一个不同的例子,一个library函数声明了一个新的library,然后创建该library的时候,在document.ready里自动执行init方法。
function library(module) { $(function() { if (module.init) { module.init(); } }); return module; } var mylibrary = library(function() { return { init: function() { /*implementation*/ } }; }());
对象自面量
对象自面量使用大括号声明,并且使用的时候不需要使用new关键字,如果对一个模块里的属性字段的publice/private不是很在意的话,可以使用这种方式,不过请注意这种方式和json的不同。对象自面量:var item={name: "tom", value:123} json:var item={"name":"tom", "value":123}。
var mymodule = { myproperty: 'somevalue', //object literals can contain properties and methods. //here, another object is defined for configuration //purposes: myconfig: { usecaching: true, language: 'en' }, //a very basic method mymethod: function () { console.log('i can haz functionality?'); }, //output a value based on current configuration mymethod2: function () { console.log('caching is:' + (this.myconfig.usecaching) ? 'enabled' : 'disabled'); }, //override the current configuration mymethod3: function (newconfig) { if (typeof newconfig == 'object') { this.myconfig = newconfig; console.log(this.myconfig.language); } } }; mymodule.mymethod(); //i can haz functionality mymodule.mymethod2(); //outputs enabled mymodule.mymethod3({ language: 'fr', usecaching: false }); //fr
commonjs
关于 commonjs的介绍,这里就不多说了,之前很多文章都有介绍,我们这里要提一下的是commonjs标准里里有2个重要的参数exports和require,exports是代表要加载的模块,require是代表这些加载的模块需要依赖其它的模块,也需要将它加载进来。
/* example of achieving compatibility with amd and standard commonjs by putting boilerplate around the standard commonjs module format: */ (function(define){ define(function(require,exports){ // module contents var dep1 = require("dep1"); exports.someexportedfunction = function(){...}; //... }); })(typeof define=="function"?define:function(factory){factory(require,exports)});
有很多commonjs标准的模块加载实现,我比较喜欢的是requirejs,它能否非常好的加载模块以及相关的依赖模块,来一个简单的例子,例如需要将图片转化成ascii码,我们先加载encoder模块,然后获取他的encodetoascii方法,理论上代码应该是如下:
var encodetoascii = require("encoder").encodetoascii; exports.encodesomesource = function(){ //其它操作以后,然后调用encodetoascii }
但是上述代码并没用工作,因为encodetoascii函数并没用附加到window对象上,所以不能使用,改进以后的代码需要这样才行:
define(function(require, exports, module) { var encodetoascii = require("encoder").encodetoascii; exports.encodesomesource = function(){ //process then call encodetoascii } });
以上就是javascript架构设计module模式用法实例详解的详细内容。
其它类似信息

推荐信息