javascript裏面變量再也不使用,就是垃圾,咱們就應該把它清除掉,以避免佔用內存。
可是垃圾回收過程是一個近似且不完美的方案,由於某塊內存是否還有用,屬於「不可斷定的」問題,意味着靠算法是解決不了的。
目前主流瀏覽器使用的是標記清除,在介紹標記清除前先介紹下爲何引用計數會被淘汰。javascript
引用計數最先由 Netscape Navigator 3.0 採用,但很快就遇到了嚴重的問題:循環引用。所謂循環引用,就是對象 A 有一個指針指向對象 B,而對象 B 也引用了對象 A。
html
function problem() { let objectA = new Object(); let objectB = new Object(); objectA.someOtherObject = objectB; objectB.anotherObject = objectA; }
在這個例子中,objectA 和 objectB 經過各自的屬性相互引用,意味着它們的引用數都是 2。在 標記清理策略下,這不是問題,由於在函數結束後,這兩個對象都不在做用域中。而在引用計數策略下objectA 和 objectB 在函數結束後還會存在,由於它們的引用數永遠不會變成 0。若是函數被屢次調 用,則會致使大量內存永遠不會被釋放。爲此,Netscape 在 4.0 版放棄了引用計數,轉而採用標記清理。前端
這裏介紹下第二步驟的一個實現。
可達性就行可訪問性,window(globle)能訪問某個變量A(無論經過幾層取值),那A就是可達的,那麼A就有可能再將來會被用,A就不會被刪除。
咱們看一下下圖就能明白,左邊可達,右邊不可達,右邊會再某個階段會v8引擎回收
java
明白了垃圾回收的概念,理解閉包就簡單多了。
閉包爲啥不銷燬,由於當前函數執行完的返回值(通常是個函數)被外層上下文中的某個變量引用了,因此閉包中的環境可達,因此不會被銷燬。
可是也由於不會被銷燬,因此咱們應該注意一下內存泄漏,也就是若是閉包占用的內存特別多,又把它賦給全局變量。並且這個操做咱們是不斷的進行的,那個內存就會越佔越多,也就是發生了內存泄漏。es6
還有個相關的考點,就是weakmap爲何不會被gc(Garbage Collection,垃圾收集)
由於它對於值的引用都是不計入垃圾回收機制的,因此名字裏面纔會有一個"Weak",表示這是弱引用。
防止內存泄漏咱們須要手動置null。
map的鍵是對象,這個引用當於永遠可達,這樣很差,會有內存泄漏。
爲了不咱們忘記置Null,es6添加了weakmap這種數據結構,只要所引用的對象的其餘引用都被清除,垃圾回收機制就會釋放該對象所佔用的內存。也就是說,一旦再也不須要,WeakMap 裏面的鍵名對象和所對應的鍵值對會自動消失,不用手動刪除引用面試
多解除引用(閉包)
優化內存佔用的最佳手段就是保證在執行代碼時只保存必要的數據。若是數據再也不必要,那麼把它設置爲 null,從而釋放其引用。這也能夠叫 做解除引用。這個建議最適合全局變量和全局對象的屬性。局部變量在超出做用域後會被自動解除引用,算法
1.垃圾回收
2.JavaScript 內存泄漏教程
3.前端面試:談談 JS 垃圾回收機制
4.MDN-內存管理
5.javascript高級程序設計第4版本segmentfault