首页 > 代码库 > 《JavaScript设计模式》深入学习 —— Module(模块)模式

《JavaScript设计模式》深入学习 —— Module(模块)模式

模块是任何强大因工程需架构中不可或缺的一部分,它通常能够帮助我们清晰地分离和组织项目中的代码单元。

(1) 对象字面量

var myObject = {
    variableKey : ‘variableValue‘,
    functionkey : function () {
        // ...
    }
};

对象字面量不需要用new运算符来进行实例化,但不能用在一个语句的开头,因为开始可能被解读为一个块的开始。在对象的外部,新成员可以使用如下赋值语句来添加到对象字面量上:

myObject.array = ‘arrayValue‘;

(2) Module(模块)模式

在JavaScript中,使用Module(模块)模式进一步模拟类的概念,通过这种方式,能够使一个单独的对象拥有公有/私有方法和变量,从而屏蔽来自全局作用域的特殊部分。产生的结果是:函数名与在页面上其他脚本定义的函数冲突的可能性降低。

1. 私有

Module模式使用闭包封装“私有”状态和组织。它提供了一种包装混合公有/私有方法和变量的方式,防止其泄露到全局作用域,并与其他开发人员的接口发生冲突。通过该模式,只需要返回一个公有API,而其他的一切则维持在私有闭包里面。

这为我们提供了一个屏蔽处理底层事件逻辑的整洁整体方案,同时暴露一个接口供应用程序的其他部分使用。该模式除了返回一个对象而不是一个函数之外,非常类似于立即调用的函数表达式。

应该说明的是,在JavaScript章没有真正意义上的“私有”。在Module模式内,由于闭包的存在,声明的变量和方法只在该模式内部可用。但在返回对象上定义的变量和方法,则可以外部使用者都可用。

2. 示例

var testModule = ( function () {
    
    var counter = 0;
    
    return {
        incrementCounter : function () {
            return ++counter;
        },
        resetCounter : function () {
            console.log( ‘Counter value prior to reset : ‘ + counter );
            counter = 0;
        }
    };
    
} )();

用法:

// 增加计数器
testModule.incrementCounter();
// 检查计数器的值并重置
testModule.resetCounter();

实际上,counter变量是完全与全局作用于隔离的,且这两个方法在其他地方也无法直接读取,表现的它像是一个私有变量,它的作用域被局限于模块的闭包之中。

下面是一个包含命名空间、公有和私有的Module模式:

var myNamespace = ( function () {
    
    var myPrivateVar = 0;
    
    var myPrivateMethod = function ( foo ) {
        console.log(foo);
    };
    
    return {
        myPublicVar : ‘foo‘,
        myPublicFunc : function ( bar ) {
            myPrivateVar++;
            myPrivateMethod(bar);
        }
    };
} )();

我们来看另一个示例,一个使用这种模式实现的购物车:

var basketModule = ( function () {
    // 私有变量
    var basket = [];
    // 私有方法
    function doSomethingPrivate () {
        // ...
    }
    function doSomethingElsePrivate () {
        // ...
    }
    // 返回暴露出的公有对象
    return {
        // 添加item到购物车
        addItem : function ( values ) {
            basket.push ( values );
        },
        // 获取购物车的item数
        getItemCount : function () {
            return basket.length;
        },
        // 私有函数公有形式别名
        doSomething : doSomethingPrivate,
        // 获取购物车里所有item的价格总值
        getTotal : function () {
            var itemCount = this.getItemCount(),
                total = 0;

            while (itemCount--) {
                total += basket[itemCount].price;
            }
            return total;
        }
    };
} )();

// 调用
basketModule.addItem({
    item : ‘bread‘,
    price : 0.5
});
basketModule.addItem({
    item : ‘apple‘,
    price : 0.3
});
console.log(basketModule.getItemCount()); // 2

(3) 总结

优点: 首先,相比真正封装的思想,他对于很多拥有面向对象背景的开发人员更加整洁,其次它支持私有数据,因此在Module模式中,代码的公有部分能够接触到私有部分,然而外界无法接触类的私有部分。

缺点: 由于我们访问公有成员和私有成员的方式不同,当我们想要改变可见性的时候,实际上我们必须要修改每一个曾经使用过该成员的地方。同样,我们也无法访问那些之后在方法里添加的私有成员。

《JavaScript设计模式》深入学习 —— Module(模块)模式