##转载

js模块化

何为模块?模块就是实现特定功能的一组方法。

模块化的好处就不多说了,我们就介绍一些基本点,可以在以后的项目开发中应用到。

1、一般的写法

简答的把函数和变量放在一起。

function m1(){
    ...
}

function m2(){
    ...
}

这种做法简单方便,但是很容易污染了全局变量,很容易与其他模块发生命名冲突,而且模块之间看不出来直接的关系。

2、对象的写法

只要在上面的基础上稍作修改就能规避很多问题,我们把模块写成一个对象,该模块的方法和成员都放到这个对象里面。

var module1 = new Objec({
    name : 'xiaoxiao',
    m1 : function(){
        ...
    },
    m2 : function(){
        ...
    }
});

通过这种方式很好的把成员和方法封装在一起了,这种方式很常用。但是它会暴露所有的成员变量,像这样module1.name = ‘xxx’的用法并不推荐使用。

3、立即执行函数的写法

我们都知道在javascript中变量的作用域是函数,所以我们可以利用自执行函数来解决上面暴露成员变量的缺点。

var module1 = (function(){
    var name = 'xiaoxiao';

    var m1 = function(){
        ...
    }

    var m2 = function(){
        ...
    }

    return {
        m1:m1,
        m2:m2
    }
})();

这种方式的关键在于return,如果没有return的内容也就没有任何意义了。

如果我们要扩展这个模块我们可以这么做:

var module1 = (function(mod){

    mod.m3 = function(){
        ...
    }

    return mod
})(module1);

在稍微演进一下,防止module1是空对象:

var module1 = (function(mod){

    mod.m3 = function(){
        ...
    }

    return mod
})(window.module1||{});

如果说为了使我们的模块独立性更强,需要用到的相关js库都要传入模块内

var module1 = (function($){

        ...

})(jQuery);

4、javascript模块规范

就像javascript一样,当我们发现他的好处后,各种规范也相继产生了。在模块化的重要性提高的同时,也产生了相应的规范。目前,比较流行的模块规范有两种:CMD和AMD。

CMD

我们先来说CommonJS,在CommonJS中,有一个全局性方法require(),用于加载模块。我们熟悉的NodeJS就是建立在CommonJS的规范上的。

假定有一个数学模块math.js,就可以像下面这样加载。

var math = require('math');

math.add(1,23);

像这样很方便的math的模块引进来。

在CMD的规范当中推崇的是依赖就近原则,我们需要用到谋个模块时就近加载。

这样的模式如果是应用在服务端还是相当不错的。

但是对于浏览器来说,如果需要的时候再去加载这个模块就会导致浏览器停止在这里等待加载。对于访问者来说这是不能容忍的。

所以针对我们特殊的环境,应用同步加载的方式是不可行的。

AMD

RequireJS就是AMD(异步模块定义)的一种实现,和我们的ajax有点儿类似,它采用依赖前置的特点,充分的利用了回调函数的优势,解决浏览器环境的问题。

这种方式也是通过require加载模块的,但不同的是他有两个参数;

require([module],callback);

第一个参数是数组,表示需要加载的模块;第二个参数就是我们的回调函数了,等前面的模块加载完成后执行。我们改写上面的例子:

require(['math'],function(math){
    math.add(1.23);
});

通过这样的方式就解决了上面出现的浏览器在加载模块时出现的假死的问题。

5、总结

本文主要讲解我们对于模块化的应用和提出了AMD和CMD这两种规范的一些优势和差别。

参考资料:

JavaSript模块规范-AMD规范与CMD规范介绍: http://blog.chinaunix.net/uid-26672038-id-4112229.html

AMD规范文档: https://github.com/amdjs/amdjs-api/wiki/AMD

CMD模块定义规范: https://github.com/seajs/seajs/issues/242

模块系统: https://github.com/seajs/seajs/issues/240

前端模块化开发的价值: https://github.com/seajs/seajs/issues/547

前端模块化开发那点历史: https://github.com/seajs/seajs/issues/588