(function(){})()构造如何工作以及人们为什么使用它?

(function() {})()及其jQuery特定的表亲(function($) {})(jQuery)一直在Javascript代码中popup。

这些结构如何工作,他们解决了什么问题?

例子赞赏

随着JavaScript框架的日益stream行, $符号被用于许多不同的场合。 所以,为了缓解可能的冲突,你可以使用这些结构:

 (function ($){ // Your code using $ here. })(jQuery); 

具体来说,这是一个匿名函数声明, 立即传递主jQuery对象作为参数执行。 在那个函数里面,你可以使用$来引用那个对象,而不必担心其他的框架也在这个范围内。

这是一种用来限制可变范围的技术; 这是防止variables污染全局名称空间的唯一方法。

 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 })(); 

1)它定义了一个匿名函数,并立即执行它。

2)通常这样做是为了不污染具有不需要的代码的全局名称空间。

3)你需要公开一些方法,里面声明的任何东西都是“私有的”,比如:

 MyLib = (function(){ // other private stuff here return { init: function(){ } }; })(); 

或者,或者:

 MyLib = {}; (function({ MyLib.foo = function(){ } })); 

重点是,有很多方法可以使用它,但结果保持不变。

这只是一个立即被调用的匿名函数。 你可以先创build一个函数然后调用它,然后得到相同的效果:

 (function(){ ... })(); 

作为:

 temp = function(){ ... }; temp(); 

你也可以用一个命名函数来做同样的事情:

 function temp() { ... } temp(); 

你调用jQuery特有的代码只是在你使用jQuery对象的意义上说的。 这只是一个带有参数的匿名函数,立即调用。

你可以分两步做同样的事情,你可以用你喜欢的任何参数来做:

 temp = function(answer){ ... }; temp(42); 

解决的问题是它为函数中的代码创build了一个closet。 您可以在其中声明variables,而不会污染全局名称空间,从而降低使用一个脚本与另一个脚本时的冲突风险。

在jQuery的特定情况下,您可以在兼容模式下使用它,它不会将名称$声明为jQuery的别名。 通过将jQuery对象发送到闭包中并为参数$命名,您仍然可以使用与没有兼容模式相同的语法。

这里解释说,你的第一个构造提供了variables的范围。

variables的作用域是在javascript中的函数级别。 这与你在C#或Java这样的语言中所使用的variables是不同的。 这意味着如果你在一个循环或者一个if语句中声明一个variables,它将会被整个函数所使用。

如果你发现自己需要明确地在函数内部定义一个variables,你可以使用一个匿名函数来做到这一点。 你实际上可以创build一个匿名函数,然后立即执行它,所有的variables将被限定在匿名函数中:

 (function() { var myProperty = "hello world"; alert(myProperty); })(); alert(typeof(myProperty)); // undefined 

这样做的另一个原因是消除您正在使用的框架$操作符的任何混淆。 比如强制jQuery,你可以这样做:

 ;(function($){ ... your jQuery code here... })(jQuery); 

通过传入$运算符作为参数并在jQuery上调用它,即使加载了其他框架,函数中的$运算符也会被locking到jQuery。

这个构造的另一个用途是“捕获”将在闭包中使用的局部variables的值。 例如:

 for (var i = 0; i < 3; i++) { $("#button"+i).click(function() { alert(i); }); } 

上面的代码将使所有三个buttonpopup“3”。 另一方面:

 for (var i = 0; i < 3; i++) { (function(i) { $("#button"+i).click(function() { alert(i); }); })(i); } 

这将使三个button按预期popup“0”,“1”和“2”。

这样做的原因是闭包保持对其封闭的栈的引用,该栈保存其variables的当前值。 如果这些variables在闭包执行之前发生变化,那么闭包只会看到最新的值,而不是闭包创build时的值。 如上面第二个例子所示,通过将闭包创build封装在另一个函数中,variablesi的当前值被保存在匿名函数的堆栈框架中。

这被认为是closures 。 这意味着所包含的代码将在其自己的词汇范围内运行。 这意味着你可以定义新的variables和函数,它们不会和闭包外的代码中使用的名字空间相冲突。

 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); 

这将生成三个popup窗口,certificate闭包中的i不会改变同名的预先存在的variables:

  • 幻数是0
  • 封闭内的幻数是99
  • 幻数仍然是0

他们经常用在jQuery插件中。 正如在jQuery插件创作指南中所解释的,在{ }中声明的所有variables都是私有的,并且在外部是不可见的,这允许更好的封装。

正如其他人所说,他们都定义了立即调用的匿名函数。 我通常在这个结构中包装我的JavaScript类的声明,以便为这个类创build一个静态的私有空间。 然后,我可以在该范围内放置常量数据,静态方法,事件处理程序或其他任何东西,只有类的实例才可见:

 // 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命名空间,所以它是可访问的。 incrementingIDsomePrivateStaticMethod()不能直接在匿名函数作用域之外访问。

这基本上是命名空间的JavaScript代码。

例如,您可以在其中放置任何variables或函数,而从外部,它们不在该范围内。 所以当你把所有东西封装在那里的时候,你不必担心冲突。

()在最后意味着自我调用。 你也可以在那里添加一个参数,它将成为匿名函数的参数。 我经常用jQuery来做这个,你可以看到为什么…

 (function($) { // Now I can use $, but it won't affect any other library like Prototype })(jQuery); 

Evan Trimboli在回答中涵盖了其余部分。

这是一个自我调用function。 有点像写作的速记

 function DoSomeStuff($) { } DoSomeStuff(jQuery); 

上面的代码是在第一行创build一个匿名函数,然后在第三行用0个参数调用它。 这有效地封装了该库中定义的所有函数和variables,因为所有函数只能在该匿名函数内部访问。

这是一个很好的做法,其背后的原因是避免使用variables和函数来污染全局名称空间,这些variables和函数可能会被整个站点的其他Javascript代码块所破坏。

为了阐明函数的调用方式,请考虑一个简单的例子:

如果包含这一行的Javascript,它将自动调用而不显式调用它:

 alert('hello'); 

所以,采取这个想法,并将其应用于此示例:

 (function() { alert('hello') //anything I define in here is scoped to this function only }) (); //here, the anonymous function is invoked 

最终的结果是相似的,因为匿名函数就像前面的例子一样被调用。

因为好的 代码的答案已经被采纳:)我会抛出一个build议,观看一些约翰Resigvideovideo1 , video2 (jQuery和JavaScript的发明者)。

video中提供了一些非常好的见解和答案。

当我看到你的问题的时候,这就是我正在做的事情。

 function(){ // some code here } 

是在javascript中定义一个匿名函数的方法。 他们可以让你在另一个函数的上下文中执行一个函数(否则你可能没有这个能力)。