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,所以我们可以像下面一样使用:
立即学习“Java免费学习笔记(深入)”;
//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 }); //frCommonJS
关于 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模式用法实例详解的详细内容,更多请关注php中文网其它相关文章!
java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号