JS垃圾回收和內存泄露

1.JS垃圾回收有幾種方式
2.什麼方式會引發內存泄露
3.如何避免內存泄漏,有幾種方式
4.JS的棧內存和堆內存
複製代碼

垃圾回收的方式

原理:垃圾收集器會按期(週期性)找出那些不在繼續使用的變量,而後釋放其內存。程序員

JS具備自動垃圾回收機制,GC(Garbage collection)不是實時的,由於開銷比較大,因此回收會按照固定的時間間隔週期性執行。算法

  • 回收方法一:標記清除
    • 當變量進入環境時,標記爲「進入環境」,離開環境時,標記爲「離開」
    • 垃圾回收器在運行的時候會給存儲在內存中的全部變量都加上標記(固然,可使用任何標記方式)。
    • 而後,它會去掉環境中的變量以及被環境中的變量引用的變量的標記(閉包)。
    • 而在此以後再被加上標記的變量將被視爲準備刪除的變量,緣由是環境中的變量已經沒法訪問到這些變量了。
    • 最後,垃圾回收器完成內存清除工做,銷燬那些帶標記的值並回收它們所佔用的內存空間。
  • 回收方法二:引用計數
    • IE七、8是用的這種方式,不推薦,IE9把DOM和BOM轉換爲真正的JS對象了,因此再也不使用引用計數
      • IE中的DOM和BOM的實現使用了C++的COM,而COM的回收機制是引用計數
    • 原理:跟蹤記錄每一個值被引用的次數,當聲明一個變量,並將這個引用類型的值賦值給該變量時,這個引用類型值的引用次數就是1
      • var a = {}; // a的引用次數是1
      • 當引用次數變爲0時,就會釋放該內存值佔用的空間
    • 循環引用時會形成內存泄露
      • 循環引用:對象A中包含指向對象B的指針,B中包含指向A的引用,當程序執行結束,引用計數不爲0,致使沒法釋放A、B
      • 解決方案:手動設置爲null,切斷變量與它此前引用的值之間的鏈接,GC在下次運行時,就會刪除這些值,並把它們回收
  • 瀏覽器的回收策略--標記清除,可是垃圾收集的時間間隔,各個瀏覽器互不相同。

內存泄漏的狀況

  • 內存泄漏:再也不用到的內存,沒有及時釋放
  • 引發內存泄露的狀況
    • 垃圾回收不會清除全局變量,全局變量會形成內存泄露
      • 緣由:局部變量只在函數的執行過程當中存在,而在這個過程當中會爲局部變量在棧或堆上分配相應的空間,以存儲它們的值,而後在函數中使用這些變量,直至函數結束,而閉包中因爲內部函數的緣由,外部函數結束並不能算是結束。 而全局變量的生命週期直至瀏覽器卸載頁面纔會結束。
      • 解決方法:使用嚴格模式
    • 未銷燬的定時器和回調函數,形成內存泄露
      • 定時器的回調函數是個閉包,閉包會形成引用的變量和函數一直保存在內存中,沒法釋放,形成內存泄露
      • 解決方法:將事件處理函數定義在外部,解除閉包,或者在定義事件處理函數的外部函數中,刪除對dom的引用。
    • DOM元素的不恰當處理
      • 雖然別的地方刪除了,但對象中仍是存在對DOM的引用,好比引用了td元素,但刪除了整個表格,實際上td元素仍然保留對其父元素的引用,致使整個表格都沒法回收
      • 解決方法:對於DOM元素的引用要及時手動置空

觸發垃圾回收的機制

  • IE6--當環境中存在256個變量、4096個對象、64k的字符串任意一種狀況的時候就會觸發垃圾回收器工做
    • 當環境中一直存在這麼多變量時,GC會一直在工做
  • IE7--觸發條件動態修改,根據垃圾回收期回收的內存分配量和程序的內存量比較
  • 垃圾回收時,也沒回中止響應,形成頁面卡頓,如何優化呢?
    • 方法1:分代回收
      • 變量存儲時區分臨時、持久區域,多回收臨時對象區,少回收持久對象區,減小每次須要遍歷的對象,從而減小每次GC耗時
    • 方法2:增量GC
      • 每次處理一點,下次再處理一點,雖然耗時短,可是中斷較多,須要上下文頻繁切換。
    • 針對不一樣場景,能夠選擇不一樣的處理方案

堆內存和棧內存

JS的數據類型有7中,其中Number、Boolean、String、Null、Symbol都是基本類型,Object、Array是引用類型。數組

  • 棧內存保存基本類型的值、指向引用類型的指針,內存大小是固定的
  • 堆內存保存的是引用類型的值,如數組和對象,內存大小是不固定的
  • 棧內存是先進後出,堆內存是按引用地址讀取
  • 操做對象時,實際操做的是對象的引用,而不是實際的對象
  • 堆內存由程序員分配,若程序員不釋放,程序結束時會有OS回收,分配方式相似鏈表
  • 棧內存由OS自動操做釋放,使用的是一級緩存,被調用時處於存儲空間,調用完畢馬上釋放
  • 堆內存放在二級緩存中,生命週期由垃圾回收算法來決定,並非一旦成爲孤兒就會被回收。
相關文章
相關標籤/搜索