这两种JavaScript模式的优缺点是什么

What are the Advantages and Disadvantages Between These Two JavaScript Patterns?

本文关键字:优缺点 是什么 模式 两种 JavaScript      更新时间:2023-09-26

这两种JavaScript模式非常相似。我想知道哪一个更好,为什么以及如何改进。

第一种方法:

"MODULE" in window || (window.MODULE = {} );
MODULE.utils = (function ($) {
    var utils = {};
    //public
    utils.todo = function() {
        //#
    }
    //private
    function init() {
        //#
    }
    init();
    return utils;
}(jQuery));

第二种方法

"MODULE" in window || (window.MODULE = {} );
MODULE.utils = (function() {
    function todo(){
        //#
    }
    function init() {
        //#
    }
    return {
        init:init
    }
})();

$(function() {
    MODULE.utils.init();
});

你的两种选择都没有太多的利弊,更多的是关于个人偏好。两者都可以进行调整,以提供更好的范围。

我有自己的偏好,它依赖于Undercore。它并没有真正促进私有变量或函数,但我很少发现这是一个问题。如果您想引入jQuery等,最好将匿名函数封装到$实际上是jQuery(或可互换库)。

正如您将在下面看到的,我的偏好需要更多的代码来让您继续工作(尽管有些代码不是必要的),但在尝试了您最初提出的一些变体后,我发现我的解决方案有助于编写更易于理解的代码,其他开发人员更容易掌握正在发生的事情,尤其是如果他们有Backbone.View的经验。

EDIT:封装在一个匿名函数中,用于演示集成jQuery和受保护的作用域。

var MyNamespace = MyNamespace || {};
(function($, MyNamespace) {
    MyNamespace.MyModule = function(options) {
        this.defaults = this.defaults || {};
        // have had trouble with _.defaults so _.extend instead
        this.options = _.extend({}, this.defaults, options);
        this.initialize.call(this);
        // define private stuff in here if you want
    };
    _.extend(MyNamespace.MyModule.prototype, {
        defaults: {
            myOption: "test"
        },
        initialize: function()
        {
            // ensure this always refers to our MyModule instance
            _.bindAll(this);
            this.$el = $("#some-widget");
            // Look Ma! log is already binded to this!
            this.$el.on("click", this.log);
        },
        setMyOption: function(value)
        {
            this.options.myOption = value;
        },
        log: function()
        {
            console.log("myOption: ", this.options.myOption);
        }
    });
})(jQuery, MyNamespace) 
var myModule = new MyNamespace.MyModule({ myOption: "Hey SO!" });
myModule.log(); // -> myOption: Hey SO!
myModule.setMyOption("Setter");
myModule.log(); // -> myOption: Setter
"MODULE" in window || (window.MODULE = {} );

为什么要这样做?我们已经在全球范围内了,对吧,所以我们可以做:

var MODULE = MODULE || {};

除此之外,唯一真正的区别(除了样式)是在第一个示例中init是从"模块"中立即调用的,而在第二个示例中,您可以在稍后的某个时间点手动调用init(即使在这种情况下是在模块加载后立即调用)。因此,如果您需要延迟对init的调用,最好是第二个;如果你想让它立即发生,第一个是最好的(除了对风格的偏好)。

第二种方法假设名为$的变量是一个接受单个参数的函数,该参数也是一个函数——可能是$ == jQuery的假设。这可能并不总是正确的。在第一种方法中,您保证$ == jQuery在模块的范围内,因为您将其作为参数传递给初始化模块的匿名函数。

除此之外,两者之间没有太大区别。我更喜欢公开公共方法的第二种方法,这样我的语法对于公共和私有方法都是一样的,并且我必须明确指定哪些方法是公共的。但这只是风格。