Javascript 閉包與變數

來源:互聯網
上載者:User

標籤:

1.閉包與變數

 JavaScript中的範圍鏈的機制引出了一個副作用,即閉包只能取得包含函數中任何變數的最後一個值。閉包所儲存的是整個變數對象,而不是某個特殊的值。

1234567891011121314 function createFunctions(){      var result=new Array();              for (var i=0;i<10;i++){          result[i]=function(){              return i;          };          return result;  var funcs = createFunctions();  for (var i=0; i < funcs.length; i++){      document.write(funcs[i]() + "<br />");  }

createFunction()函數返回一個數組。表面上看,似乎每個函數都應該返回自己的索引值,但事實並非如此,事實上每個函數的傳回值都是10.因為每個函數的範圍鏈中都包含著createFunctions()函數的使用中的物件,所以它們引用的都是同一個變數i。當createFunctions()函數返回後,變數i的值就是10,此時每個函數都引用著儲存變數i的同一個變數對象,所以每個函數返回後都是10.

當然我們可以使用匿名函數強制使閉包的行為符合預期。

12345678910111213141516 function createFunctions(){       var result=new Array();                 for (var i=0;i<10;i++){           result[i]=function(num){             return function(){               return num;           };           }(i);     }       return result;   }   var funcs = createFunctions();   for (var i=0; i < funcs.length; i++){       document.write(funcs[i]() + "<br />");   }

在重寫了前面的createFunctions()函數後,每個函數就好返回各自不同的索引值了。在這裡,我們沒有直接把閉包賦值給數值,而是定義了一個匿名函數,並將立即執行該函數的結果賦值給數組。這裡的匿名函數有一個參數num,也就是最終的函數要返回的值。在調用每個匿名函數時,我們傳入了變數i。由於函數參數按值傳遞的,所以就會將變數i的當前值複製給參數num。而在這個匿名函數內部,有建立並返回了一個訪問num的閉包。這樣依賴,result數組中的每個函數都有自己num變數的一個副本,因此就可以返回各自不同的數值了。

1.2關於this對象

在閉包中使用this對象會出現一些問題,this對象是運行時基於函數的執行環境綁定的:在全域函數中,this等於window,而當函數被當作某個對象的方法調用時,this等於那個對象。不過,匿名函數的執行環境具有全域性,因此其this對象通常指向window(當然,在通過call()和apply()改變函數執行環境時,this指向其他對象)。

1234567891011 var name="The Window"    var object={      name:"My object"    getNameFunc:function(){          return function(){              return this.name;              };              };  alert(object.getNameFunc()()); //"The Window"(在非strict 模式下)

?

以上代碼建立了一個全域變數name,有建立了一個包含那麼屬性的對象,這個對象還包括一個方法——getNameFunc(),它返回一個匿名函數,而匿名函數又返回this.name.由於getNameFunc()返會一個函數。因此調用object.getNameFunc()()就會立即返回調用它的函數,結果就返回一個字串。然而,這個例子返回的字串是“The Window”,即全域name變數的值。

但是,為什麼匿名函數沒有取得其包含範圍(或外部範圍)的this對象呢?

每個函數在調用時,其使用中的物件都會自動擷取兩個特殊的變數:this和arguments。內建函式在搜尋這兩個變數時,只會搜到其使用中的物件為止,因此永遠不肯能訪問到外部函數中的這兩個變數。不過,把外部範圍中的this對象儲存在一個閉包能夠訪問的變數裡,就可以放閉包訪問該對象了。

123456789101112 var name="The Window"    var object={      name:"My object"    getNameFunc:function(){          var that=this;         return function(){              return that.name;              };              };  alert(object.getNameFunc()()); //"My object"

 以上代碼中,我們在定義匿名函數之前,把this對象賦值給了that變數,而在定義閉包之後,閉包也可以訪問這個變數,因為它們是我們在外部函數中特意聲明的一個變數。即使在函數返回之後,this也仍然引用的object,所以調用object.getName()()就返回“My object”.

Javascript 閉包與變數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.