日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

JavaScript中的内存释放

發布時間:2023/12/13 综合教程 38 生活家
生活随笔 收集整理的這篇文章主要介紹了 JavaScript中的内存释放 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C、C++語言需要手動管理內存的分配與釋放(常用方法:malloc(), calloc(), realloc()和free()等)。而JavaScript與Java、C#相似,內置了垃圾回收器,能自動管理內存的分配與釋放。

內存生命周期:

分配內存
使用分配的內存(讀與寫操作)
當應用程序不再需要時,釋放掉已分配的內存

雖然垃圾回收器能能自動管理內存分配、釋放,但并不意味著開發者不再需要關注內存管理。因為一些不好的編碼會導致內存泄露,即應用程序不再需要的內存沒有被釋放掉。因此了解內存管理是很重要的。

Javascript中的內存分配

當聲明變量時,JavaScript會自動為變量分配內存

var numberVar = 100; //為整數分配內存
var stringVar = 'node simplified';  // 為字符串分配內存 
var objectVar = {a: 1}; // 為對象分配內存
var a = [1, null, 'abra']; // 為數組分配內存
function f(a) {
  return a + 2;
} // 為函數分配內存 

GC(Garbage collection)

垃圾回收是追蹤并釋放應用程序不再使用的內存過程。垃圾回收器通過算法來實現追蹤應用程序不再使用的內存。主要涉及的垃圾回收算法如下:

Reference-counting garbage collection(引用計數)
Mark-and-sweep algorithm(標記清除)

Reference-counting garbage collection(引用計數)

引用計數算法是一種最基礎的垃圾回收算法,當一個對象的引用數為零時,會被自動回收。該算法將一個對象的引用數為0時視為應用程序不再需要的內存。

!function (){
  var o1 = {a: {b: 2}},// 兩個對象被創建。假如分別用A:{a: {b: 2}},B:{b: 2}表示,對象B被對象A的屬性a引用,對象A被賦值給變量o1。A和B的引用數都為1,因此不能被回收。
      o2 = o1; // 將對象A賦給變量o2。此時A引用數為2,B引用數1。
      o1 = 1;// 將變量o1對對象A引用切斷。此時A引用數為1,B引用數1。
  var oa = o2.a; // 將對象B賦值給變量oa。此時A引用數為1,B引用數2。
      o2 = 'foo'; // 將變量o2對對象A引用切斷。此時A引用數為0,B引用數1。因為對象A的a屬性被變量oa引用,因此對象A不能被釋放。
      oa = null; // 將變量oa對對象B引用切斷。此時A引用數為0,B引用數0。A與B會被回收。
}()

引用計數的限制:循環引用

循環引用存在一個限制。如下實例,兩個對象相互引用,形成一個循環引用。正常情況下,當函數執行完后,對應的內存會被釋放掉。而引用計數算法會將循環引用對象的引用數都視為至少為1,因此不能被回收。

function f() {
  var o = {};
  var o2 = {};
  o.a = o2; // o references o2
  o2.a = o; // o2 references o

  return 'azerty';
}

f();

常見問題

IE6-7的DOM對象是基于計數引用算法進行垃圾回收的。而循環引用通常會導致內存泄露:

var div;
window.onload = function() {
  div = document.getElementById('myDivElement');
  div.circularReference = div;
  div.lotsOfData = new Array(10000).join('*');
};

如上述實例,DOM元素div通過自身的“circularReference”屬性循環引用自己。如果沒有顯式將該屬性刪除或設為null,計數引用垃圾回收器會始終持有至少一個引用。即使DOM元素從DOM樹種移除,DOM元素的內存會一直存在。如果DOM元素持有一些數據(如實例中“lotsData”屬性),該數據對應的內存也無法被釋放。了解更多參考--->IE<8循環引用導致的內存泄露

Mark-and-sweep algorithm(標記清除)

該算法將“對象不再需要”的定義簡化為“對象不可到達”。 這個算法假設有一組被稱為roots的對象(在JavaScript中,root就是全局對象)。垃圾回收器會定期地從這些roots開始,查找所有從根開始引用的對象,然后再查找這些對象引用的對象……。從roots開始,垃圾回收器會查找所有可到達對象,并回收不可到達的對象。

為了確定對象是否需要,該算法要確定對象是否可到達。由如下步驟組成:

垃圾回收器會創建一組roots,roots通常是持有引用的全局變量。在JavaScript中,window對象就可作為root的全局變量。
垃圾回收器會檢查所有的roots并標記為活躍狀態。然后遞歸遍歷所有的子變量。只要從root不能到達的都被標記為垃圾。
所有沒有被標記為活躍狀態的內存塊都被視為垃圾。垃圾回收器就可以釋放這部分內存并把釋放的內存返回給操作系統。

這個算法比引用計數算法更優,因為對于引用計數算法“零引用的對象”總是不可到達的,但反之則不一定,如循環引用。而標記清除算法不存在循環引用的問題。

截至2012年,所有現代瀏覽器都內置了標記清除垃圾回收器。在過去幾年里所有對JavaScript垃圾回收算法的改進(generational/incremental/concurrent/parallel garbage collection)都是基于標記清除算法來實現的,但并沒有改變標記清除算法本身和它對“對象不再需要”定義的簡化。

循環引用不再是問題

前面循環引用的實例中,在函數執行完后,兩個對象不再被全局對象可訪問的對象引用。因此這兩個對象被垃圾回收器標記為不可到達,接著被回收掉。

限制:需要明確無法到達的對象

對于這個限制,實踐中很少遇見,所以開發者不太會去關心垃圾回收機制。

參考文章:

Memory Management And Garbage Collection In Javascript
Memory Management
How JavaScript works: memory management + how to handle 4 common memory leaks
Memory Management Reference

原文地址:https://github.com/cucygh/js-leakage-patterns/blob/master/JavaScript%E5%86%85%E5%AD%98%E9%82%A3%E7%82%B9%E4%BA%8B/JavaScript%E5%86%85%E5%AD%98%E9%82%A3%E7%82%B9%E4%BA%8B.md

總結

以上是生活随笔為你收集整理的JavaScript中的内存释放的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。