(function(){代碼})()自執行函數


javascript中為何在匿名function函數后面還外加一個括號

  詳細研究過Javascript代碼庫(如Jquery、YUI)的人,一定會看到過很多如下形式的函數: (function(){...}()) 或 (function(){})()

  對於很多初學者來說,遇到它們經常會產生一系列問號:這是編程嗎,用它做什么,怎么我沒在其他語言里見過呢?

  接下來我就詳細地解釋一下:

  它可以解釋成為“匿名函數自調用”,也就是說,定義一個匿名函數,然后馬上調用它(因為它是匿名的,如果不立即調用就獲取不到該函數的引用了)。通常它被應用在一些大型的JS框架中(如上面所說的),因為這個匿名函數的函數體相當於提供一個匿名的名字空間,這樣就不會再與用戶自定義的JS函數、變量、對象發生沖突了。盡管JS沒有顯示地提供命名空間的定義和使用機制,但這種匿名方式卻不失為是一種很好的解決命名空間問題的方法。

  所以說,(function(){代碼})()就等於執行了一個函數,只不過它是匿名的而已。如果在這個匿名函數內部想再次調用這個函數,就需要調用constructor屬性了(這是Object中定義的,JS的繼承機制如同Java一樣保證了了所有對象都繼承Object類)。

  明白了它是什么了,下面我們就要學習該怎樣使用它了,以下這些問題是我們會經常遇到的,不如提前做好理論只是准備以備后期能順利地實現開發。請看下面問題:

  1、下列哪些正確?(B、C

  A.function(){

  alert("Here!");

  }();

  B.(function(){

  alert("Here!");

  })();

  C.(function(){

  alert("Here!");

  }());

  2、下列哪個結果是正確的?(A、B、C、D

  A.(function(a1,a2){

  alert("Here!"+(a1+a2));

  })(1,2);

  B.(function(a1,a2){

  alert("Here!" +(a1+a2));

  }(1,2));

  C.void function(a1,a2){

  alert("Here!" +(a1+a2));

  }(1,2);

  D.var f = function(a1,a2){

  alert("Here!" +(a1+a2));

  }(1,2);

  注:A 、B、C與D四種格式都正確,前兩者屬於同種情況的不同寫法,后兩種是將函數對象的返回值賦給其他變量,C是忽略函數返回值,而D正相反!

  具體舉個例子:

  function test(){

  return (function(p1,p2){

  return p1+p2;

  })(1,2);

  };

  (function(){

  alert(test());

  }());

  下面我們就深入研究一下這種匿名函數:

  1、

  ①

  function Foo() {

    var a = 123;

    this.a = 456;

    (function() {

      alert(a); // 123

  alert(this.a); // undefined

    })();

  };

  var f = new Foo();

  ②

  function Foo() {

    var a = 123;

    this.a = 456;

    (function(_this) {

      alert(a); // 123

  alert(_this.a); // 456

    })(this);

  };

  var f = new Foo();

  以上兩個對比,說明:

  (1)匿名函數可以直接訪問到外層署名函數(Foo)中的變量(使用關鍵字var定義的),但不能訪問外層署名函數的屬性(使用關鍵字this定義的);

  (2)匿名函數中的this指向的是匿名函數對象的地址,它與外層署名函數(Foo)對象的this指向的地址不同;

  (3)匿名函數若要訪問外層署名函數(Foo)中的屬性,可以通過參數傳遞的方式實現。

  2、

  ①

  function Foo() {

    var a = 123;

    this.a = 456;

    (function(b) {

      alert(a); // 123

  alert(b); // 456

    })(this.a);

  };

  var f = new Foo();

  ②

  (function() {

    var a = 123;

    this.a = 456;

    (function() {

      alert(a); // 123

  alert(this.a); // 456

    })();

  })();

  以上兩個對比,說明:

  (1) 匿名函數既可以直接訪問外層匿名函數中的變量,又直接可以訪問外層匿名函數中的屬性,而匿名函數卻不可以直接訪問外層已命名函數中的屬性;

  (2)以上兩種方式可以實現相同的功能。

  3、

  ①

  (function() {

    var a = 123;

  this.a = 456;

    (function() {

      alert(a); // 123

  alert(this.a); // 456

  this.b = 789;

    })();

    (function() {

  alert(this.b); // 789

    })();

  })();

  (function() {

  alert(this.a); // 456

  alert(this.b); // 789

  })();

  ②

  function Foo() {

    var a = 123;

  this.a = 456;

    (function() {

      alert(a); // 123

  alert(this.a); // undefined

  this.b = 789;

    })();

    (function() {

  alert(this.b); // 789

    })();

  };

  var f = new Foo();

  (function() {

    alert(this.a); // undefined

  alert(this.b); // 789

  })();

  以上兩個對比,說明:

  (1)匿名函數(即用兩個小括號括起來的部分)位於一個執行上下文,不論這些代碼放在哪個位置上。

  4、

  ①

  function Foo() {

  (function() {

  this.b = 789;

  })();

  (function() {

  alert(this.b); // 789

  alert(b); // 789

  var a = 0;

  alert(a); // 0

  })();

  }

  var f = new Foo();

  (function() {

  alert(this.b); // 789

  alert(b); // 789

  })();

  ②

  function Foo() {

  (function() {

  this.b = 789;

  })();

  (function() {

  alert(this.b); // 789

  alert(b); //undefined

  var b = 0;

  alert(b); // 0

  })();

  }

  var f = new Foo();

  (function() {

  alert(this.b); // 789

  alert(b); // 789

  })();

  以上兩個對比,說明:

  (1)沒有加 this取值時,如果當前 {} 中不存在同名的局部變量,則等同於加 this 處理;如果當前 {} 中存在同名的局部變量,則按常規處理。

  以上只是鄙人的粗淺見解,內容還不夠完整,還會不斷完善刪改,如其中有什么錯誤之處還望讀者諒解,真誠希望能留下您的寶貴建議,以圖修改!這里歡迎每一位愛好JS的讀者,真心希望能和你們交流心得!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM