使用对象和自执行匿名函数的 jQuery 命名空间
Posted
技术标签:
【中文标题】使用对象和自执行匿名函数的 jQuery 命名空间【英文标题】:jQuery namespacing using objects and self executing anonymous functions 【发布时间】:2013-03-12 11:27:01 【问题描述】:我正在研究使用对象和自执行匿名函数创建命名空间。哪一个被认为是更好的选择?
使用对象,提供一个唯一的名称“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;
)();
【问题讨论】:
在第二个代码块中,对console.log(myFunc2());
的调用将不会显示xyx
。相反,它会抛出ReferenceError: myFunc2 is not defined
。那是因为myFunc2
是匿名函数的本地函数。
在您的第三个代码块中,myAppName
将是 undefined
,因为您没有从函数返回任何内容。
【参考方案1】:
我的第一个答案试图解决您最初的问题并展示如何设置命名空间。我决定添加第二个答案,而不是添加到该答案中,以解决您对我的第一个答案的评论中的问题。
全局变量实际上是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
代替函数(如global3
)或在window
对象上设置属性(如global1
和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()
调用公共函数,而在匿名函数之外,我们将无法引用privateValue
或@987654341 @。
【讨论】:
【参考方案2】:将所有代码放在一个命名空间下肯定有助于避免名称冲突。如果确实发生了冲突,那么更改代码来处理它会容易得多。
如果所有内容都需要公开,您的第一个代码示例就可以了。如果您希望某些内容是私有的,请使用匿名的、立即执行的函数,如下所示:
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
视为常量。您还可以更轻松地处理有人覆盖了 window 对象的情况。
【讨论】:
谢谢。做(function ()
和var myApp = (function ()
有区别吗?还是同样的事情?我想在前者中,我像这样访问变量或函数:console.log(val1);
,在后者中像这样:console.log(myApp.val1);
。那正确吗?除此之外还有什么不同吗?
@user1448031 - 我添加了另一个答案,希望能回答您的问题。以上是关于使用对象和自执行匿名函数的 jQuery 命名空间的主要内容,如果未能解决你的问题,请参考以下文章