扩展JavaScript命名空间(IIFE)

时间:2014-02-17 15:06:26

标签: javascript object namespaces

我的命名空间是使用立即调用的函数表达式(IIFE)编写的。我的基本结构如下:

(function ($, MyObjectName, undefined) {
    "use strict";

    MyObjectName.publicFunction = function () {
        privateFunction();
    };

    var privateFunction = function () {
        document.write('hello');
    };

}(jQuery, window.MyObjectName = window.MyObjectName || {}));

//调用公共方法

MyObjectName.publicFunction();

现在我想用另一个可公开访问的对象扩展这个命名空间。从这里开始,我正在我当前的命名空间中执行另一个IIFE。见下文。

(function ($, MyObjectName, undefined) {
    "use strict";

    var ExtendedObject = (function ($, ExtendedObject, undefined) {
        "use strict";

        ExtendedObject.publicFunction = function () {
            privateFunction();
        };

        var privateFunction = function () {
            document.write('<br>hello again');
        };

    }(jQuery, window.MyObjectName.ExtendedObject = window.MyObjectName.ExtendedObject || {}));

}(jQuery, window.MyObjectName = window.MyObjectName || {}));

//从扩展名称空间

调用公共方法
MyObjectName.ExtendedObject.publicFunction();

&#39;正确&#39;这样做的方式?如果没有,我怎么能实现这个目标?

1 个答案:

答案 0 :(得分:1)

IIFE用于包含变量范围。在调用期间传递依赖性只是为了整洁,因为函数体实际上确实看到了它们。它有助于保持代码整洁,是一种可识别的模式。

但是,一旦进入IIFE,除了通过参数名称之外,你应该停止引用外部依赖。否则,整洁的努力就会浪费掉。

因此,在使用此模式构建嵌套命名空间/对象时,需要重复整个模式。

相反,只需将ExtendedObject分配给MyObjectName并重新使用外部IIFE中的任何参数(例如$)。

(function ($, MyObjectName, undefined) {
    "use strict";

    MyObjectName.ExtendedObject = (function () {
        "use strict";

        var exports = {};

        exports.publicFunction = function () {
            privateFunction();
        };

        var privateFunction = function () {
            document.write('<br>hello again');
        };

        return exports;
    }());

}(jQuery, window.MyObjectName = window.MyObjectName || {}));

因为您仍希望在ExtendedObject上使用私有和公共方法,所以我仍然使用IIFE但已将其转换为使用revealing module pattern的变体,从而构建导出(公共)功能的对象,返回 - 而不是选择性地将公共方法附加到传入的对象。我的变种&#39;是使用exports变量,当你读取公共方法的代码时,它变得更加清晰,并避免在最后重复这些成员名称的错误。

如果您希望在ExtendedObject中使用JQuery或MyObjectName的任何功能,那么您可以这样做,但不要将MyObjectName作为window.的前缀,因为这会重新引入您已经达到的长度以避免的依赖性!

这些长度以实现会员隐私已经过时了。官方JavaScript class syntax没有提供给他们,并且在构造函数中自己构建它们看起来非常笨重。

您似乎热衷于遵循最佳做法并保持代码整洁,并且您的对象暴露区域有意义。这是为了限制代码在最终用户手中的可攻击性,还是确保它在设计时不会被误用?如果是后者,那么我建议你看一下TypeScript,因为这样你就可以像JS一样强类型并拥有私有成员。然而,如果你打算将隐私扩展到你的最终用户,那么它将被公开传播给vanilla JS,所以它并不是一个理想的解决方案。

希望有所帮助。