JavaScript的模块化开发


如今,javascript的使用频率越来越高,代码量也越来越大,从页面上的一些简单的特效到数据的处理,再到复杂的交互,从pc端到移动端,几乎都离不开javascript。如果不对它们进行模块化管理的话,那么开发过程可能会变的越来越困难,页面性能也可能会越来越低下。因此,对我们的javascript进行模块化开发是很有必要的。

那么,下面就来具体看一下如何对javascript进行模块化开发。

普通写法

在最初接触javascript时,我们写程序时很可能会经常这样写:

var num1 = 1;
var num2 = 2;

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

function minus ( a, b ) {
    return a - b;
}

//test
console.log( add( num1, num2 ) ); //3
console.log( minus( num1, num2 ) ); //-1

对于这样的写法,如果逻辑很简单也就无所谓了,但如果程序很复杂、代码量比较大,这样写就很容易出问题,一个是暴露了太多的全局变量以及全局函数,容易造成命名冲突;另外就是程序结构不清晰,无论是以后维护还是团队合作,都将会很不方便。

对象字面量

对象字面量是一种键值对列表,与JSON语法格式类似。写法如下:

var count = {
    num: 1,
    add: function ( a, b ) {
        return a + b;
    },
    minus: function ( a, b ) {
        return a - b;
    }
};

// test
console.log( count.add( 1, 2) ); //3
console.log( count.minus( 6, 8 ) ); //-2

基于这种呈现形式,可以作为一种模块化的方法,比如定义一个模块名count,然后以对象字面量的形式创建内部方法,然后赋值给count,如上面例子。但这样做也不好,所有的成员变量及方法在外边都是可访问的,并且还可以任意修改,因此,这并不是一种好的方法。

匿名函数

匿名函数,从字面意思理解就是“没有名字的函数”,因为没有名字,那么也就没有办法调用,所以通常和闭包结合起来,形成一个自动执行函数。基本写法如下:

(function () {
    // do something
})();

如果需要传入参数,可以这样写:

(function ($) {
    // do something
    // $是形参,jQuery是实参
    console.log($);
})(jQuery);

对前面的例子改写后就是:

(function () {
    var num1 = 1;
    var num2 = 2;

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

    function minus ( a, b ) {
        return a - b;
    }

    //test
    console.log( add( num1, num2 ) ); //3
    console.log( minus( 6, 8 ) ); //-2
})();

这样不仅形成了私有变量和私有方法,并且也以闭包的形式形成了一个模块。

模块导出

很多时候我们需要显式的对一个模块进行命名,这样可以很方便的在页面中引用或者是模块之间的引用,那么我们只需对上面的“匿名闭包”形式稍作改动即可,改动后的程序如下:

var calculator = (function () {
    var num = 1;

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

    function minus ( a, b ) {
        return a - b;
    }

    return {
        add: add,
        minus: minus
    };
})();

console.log( calculator.add( 2, 8 ) ); // 10

这里calculator就是模块的名字,该模块向外提供了两个方法add和minus,变量num是私有的,我们可以通过calculator.add(2, 6)的形式调用。

模块扩展

如果我们需要对一个模块进行扩展,可以这样做:

<script src="calculator.js"></script>
<script>
    console.log( calculator ); //Object {add: function, minus: function}
    console.log( calculator.add( 2, 8 ) ); // 10

    // 模块扩展
    var calculator = (function ( baseModule ) {
        baseModule.multiply = function ( a, b ) {
            return a * b;
        };
        return baseModule;
    })( calculator || {} );

    console.log( calculator ); //Object {add: function, minus: function, multiply: function}
    console.log( calculator.multiply( 5, 8 ) ); //40
</script>

首先需要导入原来的模块,然后再对原来的模块进行扩展。上面代码中“calculator||{}”作为实参传入函数内部,当calculator存在时就对calculator扩展,否则就新命名一个模块(var calculator = {})。然后通过baseModule.multiply对模块增加一个属性。扩展后我们打印出calculator,就可以查看它的属性的变化。

以上就是javascript模块化开发的一些基础内容,如需进一步了解,可以研究下AMDCMD规范,也可以看下RequireJSSeaJS这两个模块加载器。

参考资料:

 http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

http://benalman.com/news/2010/11/immediately-invoked-function-expression/


发表评论

电子邮件地址不会被公开。

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>