扩展JavaScript命名空间(IIFE)

5

我的命名空间是使用立即调用的函数表达式(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();

这样做是“正确”的吗?如果不是,我该如何实现?
1个回答

3

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,但已将其转换为使用揭示模块模式的变体,它构建了一个导出(公共)功能的对象并返回该对象 - 而不是选择性地将公共方法附加到传入的对象上。我的“变体”是使用exports变量,这使得在阅读代码时更清晰哪些方法将是公共的,并避免了在结尾重复那些成员名称的容易出错的情况。
如果您希望在ExtendedObject内部使用JQuery或MyObjectName的任何功能,则可以这样做,但不要以window.作为MyObjectName的前缀,因为这会重新引入您已经尽力避免的依赖关系!
为了实现成员隐私,采取这些措施已经过时了。官方的JavaScript类语法不提供它们,并且在构造函数中自己构建它们看起来很笨拙。
您似乎很热衷于遵循最佳实践,保持代码整洁和对象公开区域的意义。这是为了限制最终用户手中的代码可破解性,还是为了确保在设计时不被错误使用?如果是后者,我建议您查看TypeScript,因为它将允许您编写代码,就好像JS是强类型和具有私有成员一样。但是,它将转译为纯JS,并且所有内容都是公共的,所以如果您打算将隐私扩展到最终用户,则不是理想的解决方案。
希望这有所帮助。

如果OP担心纯JS的公共可见性,那么代码的混淆可能是一个不错的解决方案。https://github.com/mishoo/UglifyJS2 - Ben Winding
@TylerDurden我同意丑化比基于闭包的隐私更可取。大多数环境将闭包公开给调试器,而一些良好的混淆可以使人们却步。JavaScript就是它的样子。没有必要给猪涂口红 - 相反用更多的粪便来覆盖它! :) - Raith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接