深入JavaScript(2):全面解析Module模式

@HuYuee 2016-08-21 10:58:32发表于 iuap-design/blog

简介

首先我们来看看Module模式的基本特征:

1、模块化,可重用
2、封装了变量和function,和全局的namaspace不接触,松耦合
3、只暴露可用public的方法,其它私有方法全部隐藏

关于Module模式,最早是由YUI的成员Eric Miraglia在4年前提出了这个概念,我们将从一个简单的例子来解释一下基本的用法(如果你已经非常熟悉了,请忽略这一节)。

基本用法

先看一个最简单的例子:

var Calculator = function (eq) {
    //这里可以声明私有成员
    var name = "huyue";

    return {
        // 暴露公开的成员
        add: function () {
                console.log(name);
        }
    };
};

匿名闭包

匿名闭包是让一切成为可能的基础,而这也是JavaScript最好的特性,我们来创建一个最简单的闭包函数,函数内部的代码一直存在于闭包内,在整个运行周期内,该闭包都保证了内部的代码处于私有状态。

(function () {
    // ... 所有的变量和function都在这里声明,并且作用域也只能在这个匿名闭包里
    // ...但是这里的代码依然可以访问外部全局的对象
}());

注意,匿名函数后面的括号,这是JavaScript语言所要求的,因为如果你不声明的话,JavaScript解释器默认是声明一个function函数,有括号,就是创建一个函数表达式,也就是自执行,用的时候不用和上面那样在new了,当然你也可以这样来声明:

(function () {/* 内部代码 */})();

引用全局变量

JavaScript有一个特性叫做隐式全局变量,不管一个变量有没有用过,JavaScript解释器反向遍历作用域链来查找整个变量的var声明,如果没有找到var,解释器则假定该变量是全局变量,如果该变量用于了赋值操作的话,之前如果不存在的话,解释器则会自动创建它,这就是说在匿名闭包里使用或创建全局变量非常容易,不过比较困难的是,代码比较难管理,尤其是阅读代码的人看着很多区分哪些变量是全局的,哪些是局部的。
好在在匿名函数里我们可以提供一个比较简单的替代方案,我们可以将全局变量当成一个参数传入到匿名函数然后使用,相比隐式全局变量,它又清晰又快,我们来看一个例子:

(function ($) {
    // 这里,我们的代码就可以使用全局的jQuery对象了
} (jQuery));

不过,有时候可能不仅仅要使用全局变量,而是也想声明全局变量,如何做呢?我们可以通过匿名函数的返回值来返回这个全局变量,这也就是一个基本的Module模式,来看一个完整的代码:

var blogModule = (function () {
    var my = {}, privateName = "博客园";

    function privateAddTopic(data) {
        // 这里是内部处理代码
    }

    my.Name = privateName;
    my.AddTopic = function (data) {
        privateAddTopic(data);
    };

    return my;
} ());

子模块

最后一个也是最简单的使用方式,那就是创建子模块

//parent.js   父文件
parent = (function(){
   //父模块的内容
}());
//son.js   子文件
parent.son = (function () {
    //子模块的内容
} ());