(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
命名空间,所以它是可访问的。 incrementingID
和somePrivateStaticMethod()
不能直接在匿名函数作用域之外访问。
这基本上是命名空间的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中定义一个匿名函数的方法。 他们可以让你在另一个函数的上下文中执行一个函数(否则你可能没有这个能力)。