將整個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;
     })()
    }
相關文章
相關標籤/搜索