JS閉包


閉包

  能夠訪問另一個函數作用域的變量的函數。清晰的講:閉包就是一個函數,這個函數能夠訪問其他函數的作用域中的變量。

下面inner 就是一個閉包函數,因為他能夠訪問到outer函數的作用域

1 function outer() { 2      var  a = '變量1'
3      var  inner = function () { 4  console.info(a) 5  } 6     return inner; 7 }

  閉包是站在作用域的角度上來定義的,因為inner訪問到outer作用域的變量,所以inner就是一個閉包函數。雖然定義很簡單,但是有很多坑點,比如this指向、變量的作用域,稍微不注意可能就造成內存泄露。

坑點一,引用的變量可能發生變化

1 function outer() { 2       var result = []; 3       forvar i = 0; i<10; i++){ 4         result.[i] = function () { 5  console.info(i) 6  } 7  } 8      return result 9 }

  看樣子result每個閉包函數對打印對應數字,1,2,3,4,...,10, 實際不是,因為每個閉包函數訪問變量i是outer執行環境下的變量i,隨着循環的結束,i已經變成10了,所以執行每個閉包函數,結果打印10, 10, ..., 10。這時,可以使用閉包保存臨時數據:

 1 function outer() {  2       var result = [];  3       forvar i = 0; i<10; i++){  4         result.[i] = function (num) {  5              return function() {  6  console.info(num);  7  }  8  }(i)  9  } 10      return result 11 }

此時訪問的num,是上層函數執行環境的num,數組有10個函數對象,每個對象的執行環境下的number都不一樣。

坑點二,this指向問題

1 var object = { 2      name: ''object"3  getName: function() { 4  return function() { 5  console.info(this.name) 6  } 7  } 8 } 9 object.getName()()    // underfined

因為里面的閉包函數是在window作用域下執行的,也就是說,this指向windows

坑點三,內存泄露問題

1 function showId() { 2     var el = document.getElementById("app") 3     el.onclick = function(){ 4  aler(el.id) 5  } 6 }

這樣會導致閉包引用外層的el,當執行完showId后,el無法釋放,因此需要手動置空

1 function showId() { 2     var el = document.getElementById("app") 3     var id  = el.id 4     el.onclick = function(){ 5  aler(id) 6  } 7     el = null  // 主動釋放el
8 }

技巧1,用閉包解決遞歸調用問題

function factorial(num) { if(num<= 1) { return 1; } else { return num * factorial(num-1) } } var anotherFactorial = factorial factorial = null anotherFactorial(4)

報錯 ,因為最好是return num* arguments.callee(num-1),arguments.callee指向當前執行函數,但是在嚴格模式下不能使用該屬性也會報錯,所以借助閉包來實現。

1 function newFactorial = (function f(num){ 2     if(num<1) {return 1} 3     else { 4        return num* f(num-1) 5  } 6 })

這樣就沒有問題了,實際上起作用的是閉包函數f,而不是外面的函數newFactorial。

技巧2,用閉包模仿塊級作用域

es6沒出來之前,用var定義變量存在變量提升問題,當然現在大多用es6的let 和const 定義。

 1 for(var i=0; i<10; i++){  2  console.info(i)  3 }  4 alert(i)  // 變量提升,彈出10
 5 
 6 //為了避免i的提升可以這樣做
 7 (function () {  8     for(var i=0; i<10; i++){  9  console.info(i) 10  } 11 })() 12 alert(i)  // underfined 因為i隨着閉包函數的退出,執行環境銷毀,變量回收

 


免責聲明!

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



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