js 模块化设计模式的一点见解
模块化模式可以帮助我们组织代码,尤其是随着代码的增长。有别于其他的语言,js没有特定的语法支持包,但是模块化设计模式提供了创建自我包容并减少代码碎片, 这种模式可以被认为是根据你的软件代码的需求进行函数式的可添加替换或删除。
模块化模式是几种模式的集合:
命名空间
函数及时实现
私有和专有成员
声明式依赖
首先,我们先用命名空间函数开始一个有用的模块例子,提供了一个数组:
MYAPP.namespace('MYAPP.utilities.array');
下一步定义模块。这个模式利用及时执行函数提供私有作用域。及时执行函数返回一个对象---事实上的模块和他的公共接口,提供了用户这个模块的接口。
MYAPP.utilities.array = (function () {
return {
// todo...
};
}());
下一步,添加方法和公共接口:
MYAPP.utilities.array = (function () {
return {
inArray: function (needle, haystack) {
// ...
},
isArray: function (a) {
// ...
}
};
}());
用及时执行函数提供的私有作用域,你可以声明一些私有的属性和方法,在及时执行函数的顶端,你也可以道行明任何你的模块拥有的依赖,跟着 变量的声明,你可以吧帮助设置模块化的代码选择性的一次初始化。最后的结果是一个及时执行函数返回的一个对象,包含公共接口和模块:
MYAPP.namespace('MYAPP.utilities.array');
MYAPP.utilities.array = (function () {
// dependencies
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// private properties
array_string = "[object Array]",
ops = Object.prototype.toString;
// private methods
// ...
// end var
// optionally one-time init procedures
// ...
// public API
return {
inArray: function (needle, haystack) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return true;
}
}
},
isArray: function (a) {
return ops.call(a) === array_string;
}
// ... more methods and properties
};
}());
模块模式是广泛应用和高度提倡的组织代码的方式,特别是增长型的代码。
揭露模块模式
我们已经在看私有模式时讨论过揭露模式。模块模式可以被看做所有方法都是私有的并仅仅暴露出那些你最终决定的公共api。
以上可转换为:
MYAPP.utilities.array = (function () {
// private properties
var array_string = "[object Array]",
ops = Object.prototype.toString,
// private methods
inArray = function (haystack, needle) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return i;
}
}
return −1;
},
isArray = function (a) {
return ops.call(a) === array_string;
};
// end var
// revealing public API
return {
isArray: isArray,
indexOf: inArray
};
}());
模块创建构造器
上述的例子产生了一个 Myapp.utilities.array 对象, 但是有时使用构造函数创建对象更方便,你可以用模块化来做。
惟一的区别是及时执行函数包装了模块,返回一个函数不是一个对象。
MYAPP.namespace('MYAPP.utilities.Array');
MYAPP.utilities.Array = (function () {
// dependencies
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// private properties and methods...
Constr;
// end var
// optionally one-time init procedures
// ...
// public API -- constructor
Constr = function (o) {
this.elements = this.toArray(o);
};
// public API -- prototype
Constr.prototype = {
constructor: MYAPP.utilities.Array,
version: "2.0",
toArray: function (obj) {
for (var i = 0, a = [], len = obj.length; i < len; i += 1) {
a[i] = obj[i];
}
return a;
}
};
// return the constructor
// to be assigned to the new namespace
return Constr;
}());
使用方式:
var arr = new MYAPP.utilities.Array(obj);
模块中引入全局变量
再一个共同的变化模式中,你可以传递参数给包了模块的及时执行函数,你可以传递任何参数,但是通常是全聚德变量的引用,或者是全局变量本身,引入全局变量帮众加快全局符号的解决,因为导入的变量变成了本地
MYAPP.utilities.module = (function (app, global) {
// 全局对象的引用
// 全局程序的命名空间对象
// 都变成本地变量
}(MYAPP, this));