在前幾天的一篇閉包文章中我們簡單的介紹了一下閉包,但是并沒有深入的講解,因為閉包涉及的知識點比較多,為了能夠更好的理解閉包,今天講解一下關于js中的回收機制。
在初識閉包一文中我說過js中有回收機制這么一回事,讓我們一起回顧一下,并且深入的了解js中的回收機制到底是怎么一回事。
function a(){ var num = 10; return function(){ num ++; console.log(num); } } a()(); //11 a()(); //11
按理說第二次執行函數a的時候應該打印出12才對,但是打印的卻是11,這難道不能說明js在這其中做了什么手腳嗎?按照正常邏輯我們一起來分析分析。
首先來看看我們的理解:
//我們在函數a中返回了一個匿名函數,在這個匿名函數中我們num++了一下,然后我們在函數外面執行了這個匿名函數函數,(第一括號執行函數a第二個括號執行這個rutrun回去的函數)
//現在num是11,然后我們又執行了一次這個函數,你們應該是12吧,為什么不是呢?
-------------------------------------實際js的執行-----------------------------------
但是js的設計者為了讓沒有必要的變量保存在內存中,(我們寫的任何變量都是需要內存空間的),什么叫沒有必要的變量?也就是說你不在需要這個變量的時候它就會被銷毀?那么你肯定會問js怎么知道那些變量是我們不需要的哪些是我們需要的。所以js為了知道哪些變量需要保存下來,哪些不需要保存下來,會進行一些判斷。接下來我們就一起看看js是怎么判斷的。
1.在js中定義的全局變量是不會被銷毀的,因為我們隨時都可能會用到這個變量,所以不能被銷毀。
2.但是在函數中定于的變量就不一定了,而且由于在函數的定義的變量的生命周期在執行完這個函數就銷毀的原因自然就保存不了上一次的值。
2.1但是并不是說函數就真的保存不了上一次的值,因為有的時候我們確實需要上一次的值,所以js判斷是否需要保存上一次變量的值的時候就會遵守這樣的一個規則。
規則
如果這個函數有被外部的變量引用就不會銷毀(這句話說的不夠準確,下面代碼會一步一步解釋),否則銷毀。怎么理解這句話呢?
function a(){ var b = 0; return function(){ b ++; console.log(b); } } var d = a(); d();//1 d();//2
函數a被變量變量d引用,更準確的說是函數a里面的那個匿名被變量d所引用,因為變量d等于的是函數a執行完成后的值,而函數a執行完以后又因為函數a返回了那個匿名函數,所以準確的說是變量d等于匿名函數。而這個匿名函數因為使用了函數a中的變量b并且還被變量d所引用,所以就形成了一個閉包,只要這個變量d不等于null的話,那么那個變量b會一直保存到變量d中不會被銷毀。
總結:
1、如果一個對象不被引用,那么這個對象就會被GC回收;
2、如果兩個對象互相引用,但是沒有被第3個對象所引用,那么這兩個互相引用的對象也會被回收。
如果你想更加深入學習閉包,那么我推薦你看一下關于在for循環中綁定事件打印變量i是最后一次的問題這篇文章。
文章列表