在我们最初写代码的时候,引入JS文件用script标签来引入,并且在引入多个JS文件时,当前文件所依赖的JS文件必须放在前面。也就存在一个顺序的问题,而且这是由开发者去判断和把控的。而现在前端项目越来越复杂,难免会出现很多很多script标签引入JS,这无论对于开发和维护都有着一定的缺点。所以出现了模块化的概念。
模块化的形式有很多中,比如把某个特定功能封装成一个函数,但是存在着一个问题,很有可能会出现命名冲突等问题。针对这种问题,又有了对象的方式来模块化,这种不会出现命名冲突,但是外界却可以改变对象内的成员。又有了下面这种方式:
var obj = (function(){
var name = 'liu';
var job = 'Web developer';
function sayName() {
console.log(name + ' is a ' + job);
}
return {
sayName: sayName
}
})()这样外界就不会修改没有暴露出来的对象内的变量。
上面这些是前端模块化的基础。目前通用的模块化规范主要有COMMONJS、AMD、CMD等等。
COMMONJS
COMMONJS主要是用于服务端的模块化规范,可以说NodeJS是它的最佳实践。看下面一个例子:
//导入一个文件系统模块,返回的是一个对象;
var fs = require('fs');
//调用对象的readFile方法,读文件。
fs.readFile('test.txt', function(data){
console.log(data);
});上面是一个读文件的操作,主要引入文件系统模块,这个是一个同步的过程。
当然,也可以自定义一个模块实现特定的功能。比如要实现一个Multi模块,可以这样来实现:
//multi.js
function multi(a ,b) {
return a*b;
}
module.exports = {
multi: multi
}//moduleTest.js
var obj = require('./multi.js');
var res = obj.multi(3, 4);
console.log(res);结果如下:

AMD
上面的COMMONJS规范不适合浏览器端的模块化开发,因为COMMONJS去请求模块是一个同步的过程,如果浏览器用这种规范去开发很可能会出现阻塞情况/假死情况。因此AMD规范就是为解决这种情况而出现的。
由于不是原生JS所支持的,所以AMD规范需要用到RequireJS库。
AMD的用法如下:
定义模块: define([依赖的模块], function(){ //自定义模块 });
引入模块:require([依赖的模块], function(){ //回调 })
在这里,需要说明的一点是:RequireJS是依赖前置,先去执行依赖的模块,然后再执行当前模块。
CMD
CMD典型的就是SeaJS。SeaJS与RequireJS实现上是差不多的,但是还是有一些区别,主要是在定义方式上和模块的执行时机上。
定义模块: define(function( require, exports, module ){ })
可以看到,SeaJS在定义模块的时候,并不会像RequireJS那样依赖前置,而是就近依赖的原则,需要的时候再去require。SeaJS主要是对模块先加载不执行,等到遇到require的时候才会去执行模块。
对于RequireJS和SeaJS的差异可以看下面这个例子:
//c.js
define(function(require, exports, module){
console.log('c Module');
require('./b.js');
console.log('c module finished');
})//b.js
define(function(require, exports, module){
console.log('b Module');
require('./a.js');
console.log('b module finished');
})//a.js
define(function(require, exports, module){
console.log('a Module');
})//html文件
//requirejs文件部分代码
<script src="require.min.js" data-main="c.js"></script>
//SeaJs文件部分代码
<script src="Sea.js"></script>
<script>seajs.use('./c'); </script>大家可以猜猜两种执行结果有什么不同,这里就不做验证了。
上面这些就是JS模块化的通用方法总结,当然,ES6中已经有了Module模块化的概念,后面还会再对这个进行整理。
















