JavaScript暴露模块模式

241 阅读3分钟

创作声明:如需转载,请注明出处

本文首发于知乎专栏

前言

最近在学习 JavaScript 的设计模式,在通过人民邮电出版社出版的《JavaScript设计模式》([美] Addy Osmani 著)学习的过程中,发现书中所译不仅没有体现原文的精华,而且还经常使我迷惑。

对此,我把视线投入到了网络,找到了 W3Cschool 的译本,然而也发现其中有不少地方翻译的让人很迷惑,这迫使我不得不去看原著,只是没想到原著也如此难找,最终在某个犄角旮瘩找到了。

Learning JavaScript Design Patterns

下文是由我逐字逐句研读原著过程中,根据自己的理解记录下的翻译。当然在研读的过程中也参考了 W3Cschool 的译本和人民邮电出版社出版的《JavaScript设计模式》。若有翻译不到之处,希望大家可以在评论中指正。

正文

既然我们对模块模式已经有一些了解了,让我们看一下改进版本 - Christian Heilmann 的暴露模块模式。

暴露模块模式来自于,Heilmann 对这样一个现状的不满,即当我们想要在一个公有方法中调用另外一个公有方法,或者访问公有变量的时候,我们不得不重复主对象的名称。他也不喜欢在模块模式中,当想要将某个成员变成公共成员时,必须使用对象字面量表示法。

他的努力的结果是一个更新的模式,在这个模式中,我们只需在私有范围内定义所有的函数和变量,然后返回一个匿名对象,该对象带有指向我们希望公开为公共的私有功能的指针。

如下是一个如何使用暴露模块模式的例子:

var myRevealingModule = (function () {
 
    var privateVar = "Ben Cherry",
        publicVar = "Hey there!";

    function privateFunction() {
        console.log( "Name:" + privateVar );
    }

    function publicSetName( strName ) {
        privateVar = strName;
    }

    function publicGetName() {
        privateFunction();
    }

    // 将暴露的公有指针指向到私有函数和属性上

    return {
        setName: publicSetName,
        greeting: publicVar,
        getName: publicGetName
    };

})();
 
myRevealingModule.setName( "Paul Kinlan" );

如果我们愿意,该模式还可以通过更具体的命名方案来显示私有函数和属性:

var myRevealingModule = function () {

    var privateCounter = 0;

    function privateFunction() {
        privateCounter++;
    }

    function publicFunction() {
        publicIncrement();
    }

    function publicIncrement() {
        privateFunction();
    }

    function publicGetCount(){
        return privateCounter;
    }

    // 将暴露的公有指针指向到私有函数和属性上     

    return {
        start: publicFunction,
        increment: publicIncrement,
        count: publicGetCount
    };

}();

myRevealingModule.start();

优点

该模式可以使脚本语法更加一致。在模块的最后,它也会很容易指出哪些函数和变量可以被公开访问,从而改善可读性。

缺点

该模式的一个缺点是:入股一个私有函数引用一个公有函数,在需要打补丁时,公有函数是不能被重载的。因为私有函数仍然使用的是私有的实现,并且这个模式不能用于公有成员,只用于函数。

引用私有变量 的公有对象成员也遵守无补丁规则。

因为上面的原因,使用暴露式模块模式创建的模块相对于原始的模块模式更容易出问题,因此在使用的时候需要小心。