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

Posted

技术标签:

【中文标题】声明 Javascript 命名空间的两种方式之间的区别【英文标题】:Difference between two ways of declaring Javascript namespaces 【发布时间】:2015-04-22 16:15:09 【问题描述】:

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

    (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】:

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

例如,它允许您以不同的名称重新声明某些变量 - 例如,在您的代码中,您将 jQuery 声明为 $ - 这样您就可以确定名为 @987654324 的变量@ 实际上是一个 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 调用会输出'hello world' 字符串,而第二个也是最后一个调用会输出一个原始的jQuery 对象;因此,基本上,如您所见,您可以在隔离范围内使用您喜欢的任何名称,而不会与全局变量混淆。

并考虑您在隔离函数中声明的第二个变量:privateVar - 如果您尝试从函数范围之外获取其值,您将得到 undefined 结果 - 因为该变量存在仅在您的私有“命名空间”的上下文中。

现在尝试不使用包装函数的相同示例:

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 会将页面主体的背景更改为蓝色,但第二次确实会抛出错误 - 并且所有后续调用 jQuery 都不起作用,因为您已经覆盖了全局 jQuery 变量使用您的新值(在本例中为“hello world”字符串)。

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

总结:如果您不需要私有“命名空间”变量和重新定义全局名称(例如 jQuery$),您可以坚持第二种更直接的命名空间方式。

但隔离您的内部状态几乎总是更好,所以我建议将函数范围作为一般情况。

【讨论】:

以上是关于声明 Javascript 命名空间的两种方式之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript函数的两种声明方式

0139 函数的两种声明方式

在堆栈上声明对象的两种方式之间的区别

ExtJS 3:创建自定义类的两种方式:有啥区别?

ASP.NET 中的 Javascript 命名空间声明

spring实现定时任务的两种方式