文章目录
  1. 1. JS 中的模块化编程
  2. 2. 模块的基本写法
    1. 2.1. 最简单的模块
    2. 2.2. 封装
    3. 2.3. 进一步封装
    4. 2.4. 进一步加工
    5. 2.5. 小结
  3. 3. 参考

本系列博客更像是读blog读文档的笔记,从诸多资料中梳理出了自己的认识。

JS 的模块化编程(一)- 模块的基本写法
JS 的模块化编程(二)- CommonJS
JS 的模块化编程(三)- AMD
JS 的模块化编程(四)- CMD
JS 的模块化编程(五)- AMD 和 CMD 的区别
JS 的模块化编程(六)- requireJS

JS 中的模块化编程

模块化编程:按照 “模块” 来开发软件
模块:实现特定功能的一个盒子

  1. “特定功能”-完整性
  2. “盒子”-封装性,保护私有,对外接口
  3. 与周围环境,要低耦合-独立性
  4. 与其他模块的关系-依赖性

模块化编程的好处:

  1. 给系统解藕,让代码易于维护
  2. 更专注:不关心内部实现细节,更多精力在业务逻辑
  3. 更灵活:想要什么功能,就加载什么模块

由于 JS 不是模块化编程语言,不支持类,也不支持模块(ES6 之前),所以,JS 通过其它方式在现有的环境中实现“模块”的效果。

模块的基本写法

最简单的模块

其实,一个函数就是一个模块。使用的时候,直接调用即可。 add(2,5);

1
2
3
function add(a,b){
return a+b;
}

我们把实现特定功能的一组不同函数简单的放在一起,也是一个模块

1
2
3
4
5
6
7
8
9
10
11
12
function add(a,b){
return a+b;
}
function subtract(a,b){
return a-b;
}
function multiply(a,b){
return a*b;
}
function divide(a,b){
return a/b;
}

以上的加减乘数就组成了一个 math 模块。使用的时候,直接调用就可以了
add(2,5);
subtract(2,5);
multiply(2,5);
divide(2,5);

缺点:污染了全局变量,没法保证不与其他模块发生变量名冲突

封装

封装,避免污染全局变量
我们把那些函数们放到一个对象里,把它们都包起来。对象用 JSON 字面量的形式定义,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var math = {
add: function(a,b){
return a+b;
},
subtract: function(a,b){
return a-b;
},
multiply: function(a,b){
return a*b;
},
divide: function(a,b){
return a/b;
}
};

使用时,直接调用这个对象的属性即可。
math.add(2,5);
math.subtract(2,5);

缺点:暴露模块的所有成员
当模块中有私有的属性和方法时,就不好了。

进一步封装

假设,math 中有一个私有变量 _count

1
2
3
4
5
6
7
8
9
var math = {
_count: 0,
add: function(a,b){
return a+b;
},
subtract: function(a,b){
return a-b;
}
};

对其进行进一步封装:用立即执行函数表达式,Immediately-Invoked Function Expression(IIFE)

1
2
3
4
5
6
7
8
9
10
11
12
13
var math = (function(){
var _count = 0;
var add = function(a,b){
return a+b;
};
var subtract = function(a,b){
return a-b;
};
return {
add: add,
subtract: subtract
};
})();

小结:

  1. 对内:匿名函数包裹,并立即执行
  2. 对外:返回接口
    这,就是 JS 模块的基本写法。下面再对这种写法进行下加工。

进一步加工

假设,我们想在不动 math 源码的情况下,再给它新添一个方法 max()。

1
2
3
4
5
6
7
var myMath = (function(math){
//添加新方法
math.max = function(a,b){
return a>b?a:b;
};
return math; //返回新的接口
})(math || {}); //把math当参数传进去

在使用时,我们可以

1
2
3
4
5
6
var app = (function($, math){
var val1 = $('#person1').val(),
val2 = $('#person2').val();
$('#sum').val( math.add(val1, val2) );
$('#max').val( math.max(val1, val2) );
})(jQuery, myMath); //当依赖两个模块时,类似。传两个参数

小结

  1. 模块自己
    (1)对内:良好的封装
    (2)对外:明确的接口
  2. 模块对外-与外界关系清晰明了
    (3)显示地当成参数传进来

模块的构建思想,便是通过这样的方式演化而来的。

参考

系列文章:JS 的模块化编程(一、二),通俗易懂
http://www.ruanyifeng.com/blog/2012/10/javascript_module.html
http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html

系列文章:通俗易懂
http://www.feeldesignstudio.com/2013/09/javascript-module-pattern-basics/

文章目录
  1. 1. JS 中的模块化编程
  2. 2. 模块的基本写法
    1. 2.1. 最简单的模块
    2. 2.2. 封装
    3. 2.3. 进一步封装
    4. 2.4. 进一步加工
    5. 2.5. 小结
  3. 3. 参考