声明Javascript命名空间的两种方式之间的区别

时间:2015-02-20 21:08:53

标签: javascript jquery javascript-namespaces

我通常在我的代码中使用匿名函数方法:

    (function($,NS){

    window[NS] = $.extend((window[NS] || {}), {

        global : 31,

        init : function(){
            var $d = $(document);

            $.on('click', 'a', $.proxy(this.clickHandler, this));
        },

        clickHandler : function(e){
            console.log('etc');
        }

    });

}(jQuery, "AAABBBCCC"));

但是,我最近偶然发现了一种更简单的方法,即将给定的命名空间添加到窗口对象并保护全局命名空间:

var AAABBBCCC = window.AAABBBCCC || {

    global : 31,

    init : function(){
        var $d = $(document);

        $.on('click', 'a', $.proxy(this.clickHandler, this));
    },

    clickHandler : function(e){
        console.log('etc');
    }

};

我测试了两种方法,看起来它们都在向AAABBBCCC对象的窗口对象添加。我注意不到差异。

请您解释一下这两种方法之间的区别,以及每种方法可能存在的优缺点吗?

1 个答案:

答案 0 :(得分:4)

在第一个示例中,您使用的是JavaScript函数范围。

例如,它允许您做的是重新声明不同名称下的某些变量 - 例如,在您的代码中,您将jQuery声明为$ - 这样您就可以确定名为$的变量实际上是一个jQuery对象,而不是某些其他库(如MooTools,Ext.js等)声明的变量。因此,显式函数范围的第一个优点是避免变量名称冲突。

但还有更多:在第一种情况下,您可以声明"私人"只能在"命名空间"的上下文中看到的变量功能。例如。考虑这个例子:

(function ($) {
    var jQuery = 'hello world';
    var privateVar = 42;
    console.log(jQuery); // hello  world
    console.log($); // jQuery object
})(jQuery);

console.log(jQuery); // jQuery object

第一个console.log来电会输出“你好世界”。 string,而第二个和最后一个将输出一个原始的jQuery对象;所以,基本上,正如你所看到的,你可以在你孤立的范围内使用你喜欢的任何名字而不会弄乱全局变量。

考虑在隔离函数中声明的第二个变量:privateVar - 如果你试图从函数范围之外获取它的值,你将获得{{1结果 - 因为该变量仅存在于私有"命名空间"。

的上下文中

现在尝试没有包装函数的相同示例:

undefined

这里,虽然第一次调用jQuery会将页面主体的背景更改为蓝色,但第二次调用确实会抛出错误 - 所有后续调用jQuery都不会起作用,只是因为你&# 39;用你的新值覆盖全局jQuery变量(在这种情况下 - " hello world" string)。

有关JavaScript范围界定的更多详细信息,请参阅此问题:What is the scope of variables in JavaScript?

总结:如果你不需要私人"命名空间"变量和全局名称的重新定义(例如jQuery.find('body').css('background', 'blue'); var jQuery = 'hello world'; console.log(jQuery); // hello world jQuery.find('body').css('background', 'red'); // an error occurred here jQuery),您可以坚持第二种更直接的命名空间方式。

但是,隔离内部状态几乎总是更好,因此我建议将功能范围作为一般情况。