js回收機制

今天總結下js的回收機制。前端

提及js的回收機制,必定要先說js的內存分配了。瀏覽器

內存分配

前端的同窗們確定知道,js的變量分爲基本類型和引用類型。安全

  • 基本類型
    js的基本類型有String,Number,Boolean,Null,Undefined,這些變量在內存中佔用固定的空間大小,聲明以後會被分配到棧內存中,咱們是按值訪問的。
  • 引用類型
    js的引用類型的值大小是不固定的,須要經過引用來找到相應的值,在棧內存中會分配空間存放引用類型在堆內存中的地址,在堆內存中會存放對應的值。由於地址的大小是固定的,因此能夠存在棧內存中,須要用到的時候,會到棧內存中先找到這個引用地址,而後再在堆中找到這個值。

爲何內存還要區分堆內存和棧內存呢?這裏就要說到js的垃圾回收機制了。閉包

爲何會有垃圾回收呢?固然是爲了使程序運行時的內存最小啦。性能

當一個方法執行的時候,會有部份內存用來存方法中聲明的變量,這些變量都被存在棧內存中,當方法結束的時候,這個棧內存中的變量(除了地址之外)都會被銷燬。優化

可是當咱們聲明一個對象的時候,這個對象在其餘地方也被引用了,這個對象的大小是不固定的,會被分配到堆內存中,隨着方法的結束,這個堆內存也不會被銷燬,由於其餘地方還在引用(方法的傳參等等),除非這個對象的引用爲0,垃圾回收機制纔會在覈實以後銷燬他,這裏就牽扯到了垃圾回收中的引用計數,下面會講到。操作系統

內存聲明週期

內存聲明週期:線程

  1. 分配你所須要的內存
  2. 使用分配到的內存讀和寫
  3. 不須要時將其釋放

在js中,第三部分是自動完成的,由於js中有自動垃圾回收機制。在編寫js時,不須要關心內存的使用問題,所需內存的分配和內存的釋放都是自動完成的。對象

內存泄漏

什麼狀況下會內存泄漏?能夠這麼理解,就是有些代碼原本應該要被回收的,可是沒有被回收,因此一直佔用着操做系統的內存,從而越積越多。通常的內存泄漏其實可有可無,可怕的是內存泄漏引發的堆積,致使GC一直沒辦法使用所佔用的內存給其餘程序使用。遞歸

內存溢出

內存溢出就是程序向系統申請必定大小的內存,可是系統知足不了。

管理內存

處於安全的考慮,通常狀況下系統給瀏覽器的內存會比給客戶端的內存要少,即便瀏覽器內存泄漏了或者內存溢出了也不會讓系統崩潰。內存限制的問題不只會影響到給變量分配的內存,也會影響每一個線程最多能執行的語句數量。

因此爲了確保在有限的內存中可讓頁面得到最好的性能,優化內存佔用的最佳方式就是將其值設置爲null來釋放其引用。這個方法叫作解除引用,適用於全局變量和全局對象的屬性,局部變量在離開執行環境以後就會自動被解除引用。

解除引用並不意味着立刻回收該值所佔用的內存,解除引用的真正做用是讓值離開執行環境,讓GC下次運行時自動將其回收。

垃圾回收

js的垃圾回收通常有兩種,標記清除和引用計數。

標記清除

GC在運行時會給儲存在內存中的全部變量加上標記,而後會去掉環境中的變量和被環境中的變量引用的變量的標記,在此以後被加上標記的變量被視爲要刪除的變量。而後GC完成內存清除。
標記清除會遵循如下幾種狀況:

  1. 在js中,全局變量和window對象會一直存在,不會被GC回收
  2. 遞歸所用到的全部方法和變量,不會被GC回收
  3. 閉包裏用到的變量,不會被GC回收
  4. 全部被標記的,都被認爲是垃圾,GC會啓動其回收機制,釋放內存。

引用計數

當對象被引用次數爲0時,就被回收。潛在的一個問題是:循環引用時,兩個對象都至少被引用了一次,將不能自動被回收。因此致使,咱們常講的內存泄露。

相關文章
相關標籤/搜索