不說官方給的定義,感受本身剛開始看也不是很理解。閉包
閉包 : 其實就是 該函數能使用函數外定義的變量。函數
爲何要使用閉包?spa
首先來講一下局部變量和全局變量的危害: 全局變量容易全局污染,局部變量又沒法共享,不能長久保存code
那閉包實現了一個什麼?對象
既能夠共享,長久保存,又不會全局污染,實際上是用來保護局部變量的。blog
閉包有什麼缺點?內存
佔內存,至於爲何佔內存,稍後會畫內存圖來講明。作用域
若是說你要寫一個閉包,就是抓住閉包的三個特色:get
function outer(){ var n = 1; function inner(){ return n++; } return inner; } var getNum = outer();
因此說在你判斷閉包的時候通常是看如下三點:io
那一個閉包咱們又如何去判斷他的執行結果呢?
好比剛剛那個例子來講:
function outer(){ var n = 1; function inner(){ return n++; } return inner; } var getNum = outer(); //外層函數調用一次,有一個被保護的n console.log(getNum()); //0 console.log(getNum()); //1 var getNum2 = outer(); //外層函數被調用兩次,有兩個互不干擾的n console.log(getNum2()); //0
內存圖:
建立函數的同時會建立兩個對象:
函數對象:函數的定義 (老闆)
做用域鏈對象:保存了函數對象可用的變量的位置的對象(棧),默認第一項指向window(管理員)
而調用函數時,又會建立一個新對象
活動對象:專門保存局部變量的對象(這裏說一下函數中的局部變量指的是 參數 和 var聲明的)
在做用域鏈對象中追加指向活動對象的引用
調用後:僅僅釋放了活動對象,做用域鏈中活動對象的引用出棧,活動對象因無人引用而釋放
(也就是說內存圖中,某一塊當沒有人指入它時,就會被釋放)
除去釋放後的部分:
可見若是有閉包的存在,實際上是很佔內存的,它會造成這種循環的指入,使得沒法被釋放