4

我正在研究使用对象和自执行匿名函数创建命名空间。哪个被认为是更好的选择?

使用对象,是否提供一个唯一的名称“myAppName”足以防止冲突?

var myAppName = { 
    val1: "abc", 
    val2: "xyz",
    myFunc1: function() {
      return this.val2;  
    }
}

console.log(myAppName.val1);  // abc
console.log(myAppName.myFunc1());  // xyz

使用自执行匿名函数:

(function () {
val1 = "abc";
    var val2 = "xyz";

    myFunc1 = function() {
        return val1;   
    }

    var myFunc2 = function() {
        return val2;
    }
})();

console.log(val1);  // abc
console.log(myFunc1());  // abc
console.log(myFunc2());  // xyz

在上面的自执行功能代码中,它们似乎都在执行。在变量和函数名之前使用和不使用 var 是否有含义?我不太明白。有没有办法使变量和函数成为私有和公共的?还是自执行函数中的所有内容都是私有的?

如果我在下面的自执行函数之前使用“var”会发生什么?

var myAppName = (function () {
val1 = "abc";
    var val2 = "xyz";

    myFunc1 = function() {
        return val1;   
    }

    var myFunc2 = function() {
        return val2;
    }
})();
4

2 回答 2

4

将所有代码放在一个命名空间下肯定有助于避免名称冲突。如果确实发生了冲突,那么更改代码来处理它会容易得多。

如果所有内容都需要公开,那么您的第一个代码示例很好。如果您希望某些东西是私有的,请使用匿名的、立即执行的函数,如下所示:

var myApp = (function() {
    var privateValue = 'abc'; // Don't forget "var" here.

    function privateFunction() {
        return privateValue;
    }

    return {
        publicValue: 'xyz',

        publicFunction: function() {
            return privateFunction();
        }
    }
})();

注意匿名函数如何返回一个包含公共变量和函数的对象。如果你没有把“var”放在“privateValue”之前,那么你就没有定义一个局部变量;相反,您正在引用一个全局变量(这实际上是“窗口”对象的一个​​属性。)

如果您使用的是 jQuery,我推荐以下内容:

(function(window, $, undefined) {

    var myApp = (function() {
        var privateValue = 'abc'; // Don't forget "var" here.

        function privateFunction() {
            return privateValue;
        }

        return {
            publicValue: 'xyz',

            publicFunction: function() {
                return privateFunction();
            }
        }
    })();

    // Put myApp in the global scope.
    window.myApp = myApp; 

})(window, jQuery);

这样,您可以安全地使用$()而不是jQuery(). 您也可以安全地undefined视为常数。您还可以更轻松地处理有人覆盖了窗口对象的情况。

于 2013-03-22T15:36:06.573 回答
4

我的第一个答案试图解决您最初的问题并展示如何设置命名空间。我决定添加第二个答案,而不是添加到该答案中,以解决您对我的第一个答案的评论中的问题。

全局变量实际上是window对象的属性。如果var在函数外部使用,则定义了一个全局变量。如果var在函数内部使用,则定义了一个局部变量。如果你引用一个变量someValue而不用声明它var,它与引用相同window.someValue

以下代码显示了设置全局变量的不同方法,以及定义局部变量的一种方法。

window.global1 = 'abc';
global2 = 'def';
var global3 = "ghi";

(function() {
    window.global4 = 'jkl';
    global5 = 'mno';
    var local1 = 'xyz';
})();

console.log(global1); // 'abc'
console.log(global2); // 'def'
console.log(global3); // 'ghi'
console.log(global4); // 'jkl'
console.log(global5); // 'mno'
console.log(local1);  // ReferenceError: local1 is not defined

通常,您希望限制设置全局变量(至少在创建 JavaScript 库时)。命名空间基本上只是一个全局变量。当您将其他所有内容放在该名称空间下时,您只添加了一个全局变量。

global2我认为避免设置类似及global5以上的全局变量也是一种最佳做法。相反,您应该使用var函数的 oustide(如global3)或在window对象上设置属性(如global1and global4)。

从我的另一个答案中借用代码示例,我们可以创建一个这样的命名空间:

var myApp = (function() {
    var privateValue = 'abc'; // Don't forget "var" here.

    function privateFunction() {
        return privateValue;
    }

    return {
        publicValue: 'xyz',

        publicFunction: function() {
            return privateFunction();
        }
    }
})();

我们可以通过执行以下操作来实现相同的效果,但我认为这种风格很糟糕:

(function() {
    var privateValue = 'abc'; // Don't forget "var" here.

    function privateFunction() {
        return privateValue;
    }

    myApp = {
        publicValue: 'xyz',

        publicFunction: function() {
            return privateFunction();
        }
    }
})();

在这两种情况下,我们都设置了myApp全局变量,但我认为前者比后者更清楚。

需要明确的是,在这两种情况下,我们都会将公共变量称为myApp.publicValue并使用 调用公共函数myApp.publicFunction(),而在匿名函数之外,我们将无法引用privateValueor privateFunction

于 2013-03-23T04:01:58.320 回答