最近,我已经阅读了不少Javascript,而且一直注意到整个文件都像下面这样封装在要导入的.js文件中。 html
(function() { ... code ... })();
为何这样作而不是使用一组简单的构造函数呢? html5
这就是所谓的关闭。 它基本上将代码密封在函数内部,以便其余库不会干扰它。 这相似于以编译语言建立名称空间。 jquery
例。 假设我写: web
(function() { var x = 2; // do stuff with x })();
如今其余库没法访问我在库中建立的变量x
。 canvas
浏览器中的JavaScript实际上仅具备两个有效范围:函数范围和全局范围。 浏览器
若是变量不在函数范围内,则在全局范围内。 并且全局变量一般是很差的,所以这是一种将库的变量保留给本身的构造。 闭包
一般是到名称空间(请参阅下文)并控制成员函数和/或变量的可见性。 能够将其视为对象定义。 jQuery插件一般是这样写的。 app
在Javascript中,您能够嵌套函数。 所以,如下是合法的: 函数
function outerFunction() { function innerFunction() { // code } }
如今,你能够调用outerFunction()
但的可见性innerFunction()
被限制的范围outerFunction()
这意味着它是专用于outerFunction()
它基本上遵循与Javascript中的变量相同的原理: 性能
var globalVariable; function someFunction() { var localVariable; }
相应地:
function globalFunction() { var localFunction1 = function() { //I'm anonymous! But localFunction1 is a reference to me! }; function localFunction2() { //I'm named! } }
在上述状况下,您能够在任何地方调用globalFunction()
,但不能调用localFunction1
或localFunction2
。
在编写(function() { ... code ... })()
,您正在作的是在函数文字内部编写代码(这意味着整个“对象”其实是一个函数)。 以后,您将自动调用该函数(final ()
)。 所以,正如我前面提到的,此方法的主要优势是您能够拥有私有方法/函数和属性:
(function() { var private_var; function private_function() { //code } })()
在第一个示例中,globalFunction()是能够调用以访问公共功能的公共函数,可是在上面的示例中,您如何调用它? 在这里,自调用功能使代码在启动时自动运行。 就像您能够添加initMyStuff(); 到任何.js文件的顶部,它将自动做为全局范围的一部分运行,该自调用函数也将自动运行,尽管因为它是一个未命名的函数,所以不能像initMyStuff()那样屡次调用。
整洁的事情是,您还能够在内部定义事物并将其公开给外部世界(例如,命名空间的示例,所以您基本上能够建立本身的库/插件):
var myPlugin = (function() { var private_var; function private_function() { } return { public_function1: function() { }, public_function2: function() { } } })()
如今您能够调用myPlugin.public_function1()
,但没法访问private_function()
! 所以很是相似于类定义。 为了更好地理解这一点,我建议如下连接以供进一步阅读:
编辑
我忘了提。 在final ()
,您能够传递您想要的任何内容。 例如,当您建立jQuery插件时,您像这样传递jQuery
或$
:
(function(jQ) { ... code ... })(jQuery)
所以,您在这里要作的是定义一个带有一个参数的函数(称为jQ
,一个局部变量,而且仅对该函数已知)。 那么你的自我调用函数,并传递一个参数(也称为jQuery
,可是这一次是从外面的世界,并以实际的jQuery自身的引用)。 这样作并无紧迫的需求,可是有一些优势:
早先,我描述了这些函数如何在启动时自动运行,可是若是它们自动运行,谁传入参数? 该技术假定全部参数都定义为全局变量。 所以,若是未将jQuery定义为全局变量,则此示例将不起做用,而且因为咱们的示例是匿名函数,所以没法以任何其余方式调用。 您可能会猜到,jquery.js在初始化期间所作的一件事是定义了一个'jQuery'全局变量,以及它更为著名的'$'全局变量,它使该代码在包含jquery.js以后能够工做。
除了将变量保留在本地以外,一种很是方便的用法是在使用全局变量编写库时,能够给它一个较短的变量名,以在库中使用。 它常常用于编写jQuery插件,由于jQuery容许您使用jQuery.noConflict()禁用指向jQuery的$变量。 若是禁用它,您的代码仍然可使用$而且只要您这样作就不会中断:
(function($) { ...code...})(jQuery);
您也能够将函数闭包用做较大表达式中的数据 ,就像这种肯定浏览器对某些html5对象支持的方法同样。
navigator.html5={ canvas: (function(){ var dc= document.createElement('canvas'); if(!dc.getContext) return 0; var c= dc.getContext('2d'); return typeof c.fillText== 'function'? 2: 1; })(), localStorage: (function(){ return !!window.localStorage; })(), webworkers: (function(){ return !!window.Worker; })(), offline: (function(){ return !!window.applicationCache; })() }