将整个Javascript文件包装在匿名函数(例如“(function(){…})()”)中的目的是什么?

最近,我已经阅读了不少Javascript,而且一直注意到整个文件都像下面这样封装在要导入的.js文件中。 html

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

为何这样作而不是使用一组简单的构造函数呢? html5


#1楼

这就是所谓的关闭。 它基本上将代码密封在函数内部,以便其余库不会干扰它。 这相似于以编译语言建立名称空间。 jquery

例。 假设我写: web

(function() {

    var x = 2;

    // do stuff with x

})();

如今其余库没法访问我在库中建立的变量xcanvas


#2楼

浏览器中的JavaScript实际上仅具备两个有效范围:函数范围和全局范围。 浏览器

若是变量不在函数范围内,则在全局范围内。 并且全局变量一般是很差的,所以这是一种将库的变量保留给本身的构造。 闭包


#3楼

一般是到名称空间(请参阅下文)并控制成员函数和/或变量的可见性。 能够将其视为对象定义。 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() ,但不能调用localFunction1localFunction2

在编写(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以后能够工做。


#4楼

除了将变量保留在本地以外,一种很是方便的用法是在使用全局变量编写库时,能够给它一个较短的变量名,以在库中使用。 它常常用于编写jQuery插件,由于jQuery容许您使用jQuery.noConflict()禁用指向jQuery的$变量。 若是禁用它,您的代码仍然可使用$而且只要您这样作就不会中断:

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

#5楼

您也能够将函数闭包用做较大表达式中的数据 ,就像这种肯定浏览器对某些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;
     })()
    }
相关文章
相关标签/搜索