前言:对于JS的模块化编程,一直都处于边学边用的状态,借着此次重构代码的机会,对“JS模块化编程”做一个系统的完整的学习和整理。(随时更新)
参考文章:http://www.ruanyifeng.com/blo...
什么是模块化编程?为什么需要模块化编程?
当一个项目越来越大,那么它包含的JS也会越来越多。过多的JS文件会降低代码的可读性,同时增加后续的开发和维护成本。容易出现一下情景:
“大神,为什么这个js在执行的时候会报错?我命名包含进来了呀?”
“我看看...(5分钟后),汗你这有问题。B.JS依赖于A.JS,所以引入时候要放在A.JS的后面,不然会报错。”
为了降低以上现象,引入模块化编程思想,类似强类型语言的“类”、“模块”。一个模块(JS文件)完成一类功能,需要某功能时,引入其对应的模块(JS文件)即可。
如何进行模块化编程?
模块化是一个思想,当把“同一类”功能的方法(或函数)放到一起,形成一个“类”,我们就可以把它们当成一个模块:
function m1(){ //计算手续费...
//...
}
function m2(){ //计算收益...
//...
}
这样,m1和m2就算是组成一个模块了。但是,这样的写法“污染”了全局变量。比如,此时新来了一个同事C,他不知道m1、m2已经被前辈“占”用了,然后自己写了一个“模块”,也包含了名为m1、m2的方法。同事C在自己代码里引用以上模块时,就会出现同名方法。为了避免以上问题,又对模块化进行“升级”。
模块化编程形成
将模块写成对象,这样即使重名了,因为方法属于不同对象,所以不会造成冲突:
var module1 = new Object({
_count : 0,
m1 : function (){
//...
},
m2 : function (){
//...
}
});
这样一来,同事C即使自己写了一个模块(对象),模块(对象)里包含同名方法也不需要担心冲突了
模块化编程演变
有一天,技术大佬找到同事C,说他写的模块有问题,同事D在调用的时候发现BUG。同事C一脸懵逼的跑回座位上看着自己写的模块,心里泛着低估“自己命名都用了那么久了,没啥问题”。查看了一下同事D的代码后,发现同事D不小心将他代码里边的变量_count变成了空字符串:
module1._count=""
所以在使用其他方法的时候才报错,于找到同事D痛批了一顿...
后来回到座位上,同事C思考了,虽然只是不小心,但是万一其他人也不小心那可不行。于是,同事C想到了java里边的private变量,如果让所有模块都只暴露出方法,而不暴露属性,这样就可以避免了这个问题的再次发生。
模块化编程的雏形
通过“立即执行函数”,单独将需要暴露出来的方法返回:
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();
模块化编程的改造
同事C在开发的时候,引入了一个很久以前写了模块,他发现一个问题:如果要在原先写好的模块上新增功能,那么就必须要改这个模块,但是这么一来就有可能影响到其他使用这个模块的项目。如果再准备一个新的模块,然后把原来写好的模块复制出来,然后在这模块上新增功能,这样就出现重复代码了。后来经过细心的斟酌,同事C改装一下自己的模块,增加模块的扩展性:放大模式。
var module1 = (function (mod){
mod.m3 = function () {
//...
};
return mod;
})(module1);
模块化的规范:AMD(异步模块定义,Asynchronous Module Definition)
AMD规定,采用require()方法进行加载模块。require()包含两个参数:模块、回调函数。
require([module], callback);
第一个参数:模块,表示当前JS文件(也可以是模块)包含哪些模块;
第二个参数:回调函数,当所需的模块(第一个参数)被从服务器中下载并加载完成后进行调用。
AMD的实现
待更新...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。