(function() {})()
及其jQuery特定的表兄(function($) {})(jQuery)
一直在Javascript代码中弹出。
这些结构如何运作,以及它们解决了哪些问题?
赞赏的例子
答案 0 :(得分:72)
随着JavaScript框架的日益普及,$
符号被用于许多不同的场合。因此,为了减轻可能的冲突,您可以使用这些结构:
(function ($){
// Your code using $ here.
})(jQuery);
具体来说,这是一个匿名函数声明,它将立即执行作为参数传递主jQuery对象。在该函数中,您可以使用$
来引用该对象,而不必担心其他框架也在范围内。
答案 1 :(得分:40)
这是一种用于限制变量范围的技术;这是防止变量污染全局命名空间的唯一方法。
var bar = 1; // bar is now part of the global namespace
alert(bar);
(function () {
var foo = 1; // foo has function scope
alert(foo);
// code to be executed goes here
})();
答案 2 :(得分:19)
1)它定义了一个匿名函数并立即执行它。
2)通常这样做是为了不用不需要的代码污染全局命名空间。
3)你需要从中公开一些方法,内部声明的任何东西都是“私有的”,例如:
MyLib = (function(){
// other private stuff here
return {
init: function(){
}
};
})();
或者,或者:
MyLib = {};
(function({
MyLib.foo = function(){
}
}));
关键是,有很多方法可以使用它,但结果保持不变。
答案 3 :(得分:9)
它只是一个立即调用的匿名函数。您可以先创建该函数然后调用它,然后获得相同的效果:
(function(){ ... })();
的工作原理为:
temp = function(){ ... };
temp();
您也可以对命名函数执行相同的操作:
function temp() { ... }
temp();
您调用jQuery特定的代码只是在您使用jQuery对象的意义上。它只是一个带参数的匿名函数,可以立即调用。
你可以分两步完成同样的事情,你可以用你喜欢的任何参数来做:
temp = function(answer){ ... };
temp(42);
这解决的问题是它为函数中的代码创建了一个闭包。您可以在其中声明变量而不会污染全局命名空间,从而降低使用一个脚本和另一个脚本时发生冲突的风险。
在jQuery的特定情况下,您在兼容模式下使用它,它不会将名称$声明为jQuery的别名。通过将jQuery对象发送到闭包并命名参数$,您仍然可以使用与没有兼容模式相同的语法。
答案 4 :(得分:7)
它解释了here您的第一个构造为变量提供了范围。
变量的作用域是javascript中的函数级别。这与您在C#或Java等语言中的习惯不同,其中变量的作用域为块。这意味着如果在循环或if语句中声明变量,它将可用于整个函数。
如果您发现自己需要在函数内显式扩展变量,可以使用匿名函数来执行此操作。您实际上可以创建一个匿名函数,然后立即执行它,并且内部的所有变量都将作用于匿名函数:
(function() {
var myProperty = "hello world";
alert(myProperty);
})();
alert(typeof(myProperty)); // undefined
答案 5 :(得分:6)
执行此操作的另一个原因是消除您正在使用的框架$
运算符的任何混淆。例如,要强制执行jQuery,您可以执行以下操作:
;(function($){
... your jQuery code here...
})(jQuery);
通过传入$
运算符作为参数并在jQuery上调用它,即使你加载了其他框架,函数中的$
运算符也会被锁定为jQuery。
答案 6 :(得分:5)
此构造的另一个用途是“捕获”将在闭包中使用的局部变量的值。例如:
for (var i = 0; i < 3; i++) {
$("#button"+i).click(function() {
alert(i);
});
}
以上代码将使所有三个按钮弹出“3”。另一方面:
for (var i = 0; i < 3; i++) {
(function(i) {
$("#button"+i).click(function() {
alert(i);
});
})(i);
}
这将使三个按钮按预期弹出“0”,“1”和“2”。
这样做的原因是闭包保持对其封闭堆栈 frame 的引用,该堆栈保存其变量的当前值。如果这些变量在闭包执行之前发生变化,那么闭包只会看到最新的值,而不是创建闭包时的值。通过将闭包创建包装在另一个函数中,如上面的第二个示例所示,变量i
的当前值保存在匿名函数的堆栈框架中。
答案 7 :(得分:4)
这被视为closure。这意味着包含的代码将在其自己的词法范围内运行。这意味着您可以定义新的变量和函数,它们不会与闭包之外的代码中使用的命名空间冲突。
var i = 0;
alert("The magic number is " + i);
(function() {
var i = 99;
alert("The magic number inside the closure is " + i);
})();
alert("The magic number is still " + i);
这将生成三个弹出窗口,证明闭包中的i
不会改变同名的预先存在的变量:
答案 8 :(得分:2)
它们经常用在jQuery插件中。正如jQuery Plugins Authoring Guide中所解释的,{ }
内声明的所有变量都是私有的,外部不可见,这样可以更好地封装。
答案 9 :(得分:2)
正如其他人所说,他们都定义了立即调用的匿名函数。我通常将此JavaScript类声明包装在此结构中,以便为该类创建静态专用作用域。然后我可以放置常量数据,静态方法,事件处理程序或该范围内的任何其他内容,它只对类的实例可见:
// Declare a namespace object.
window.MyLibrary = {};
// Wrap class declaration to create a private static scope.
(function() {
var incrementingID = 0;
function somePrivateStaticMethod() {
// ...
}
// Declare the MyObject class under the MyLibrary namespace.
MyLibrary.MyObject = function() {
this.id = incrementingID++;
};
// ...MyObject's prototype declaration goes here, etc...
MyLibrary.MyObject.prototype = {
memberMethod: function() {
// Do some stuff
// Maybe call a static private method!
somePrivateStaticMethod();
}
};
})();
在此示例中,MyObject
类已分配给MyLibrary
命名空间,因此可以访问。 incrementingID
和somePrivateStaticMethod()
不能在匿名函数范围之外直接访问。
答案 10 :(得分:2)
这基本上是 namespace 你的JavaScript代码。
例如,您可以在其中放置任何变量或函数,并且从外部来看,它们不存在于该范围内。因此,当您将所有内容封装在那里时,您不必担心冲突。
最后的()
意味着自我调用。您还可以在那里添加一个参数,它将成为您的匿名函数的参数。我经常使用jQuery执行此操作,您可以看到原因......
(function($) {
// Now I can use $, but it won't affect any other library like Prototype
})(jQuery);
Evan Trimboli涵盖了answer中的其他内容。
答案 11 :(得分:1)
这是一个自我调用的功能。有点像写作的简写
function DoSomeStuff($)
{
}
DoSomeStuff(jQuery);
答案 12 :(得分:1)
上面的代码正在做的是在第1行创建一个匿名函数,然后在第3行用0参数调用它。这有效地封装了该库中定义的所有函数和变量,因为所有函数只能在匿名函数内部访问。
这是一种很好的做法,其背后的原因是避免使用变量和函数污染全局命名空间,这可能会被整个站点中的其他Javascript破坏。
为了阐明函数的调用方式,请考虑一个简单的例子:
如果您包含这一行Javascript,它将自动调用而不显式调用它:
alert('hello');
所以,采取这个想法,并将其应用于这个例子:
(function() {
alert('hello')
//anything I define in here is scoped to this function only
}) (); //here, the anonymous function is invoked
最终结果类似,因为匿名函数的调用与前一个示例类似。
答案 13 :(得分:1)
因为已经采取好 代码答案:)我会提出建议,观看一些John Resig视频 video 1 ,{ {3}} (jQuery的发明者和JavaScript的主人)。
视频中提供了一些非常好的见解和解答。
这就是我在看到你的问题时碰巧做的事情。
答案 14 :(得分:0)
function(){ // some code here }
是在javascript中定义匿名函数的方法。它们可以让你在另一个函数的上下文中执行函数(否则你可能没有这个函数)。