站長資訊網
        最全最豐富的資訊網站

        javascript有gc嗎

        javascript中有GC(垃圾回收機制)。JavaScript是使用垃圾回收機制的語言,執行環境負責在代碼執行時管理內存,會自動將垃圾對象(沒有被引用的對象)從內存中銷毀。

        javascript有gc嗎

        本教程操作環境:windows7系統、javascript1.8.5版、Dell G3電腦。

        JavaScript 中的垃圾回收機制(GC)

        垃圾回收相關概念

        ① 什么是垃圾

        沒有被使用(引用)的對象就是垃圾

        ② 什么是垃圾回收

        沒有被引用的對象被銷毀,內存被釋放,就是垃圾回收

        C、C++ 等編程語言需要手動垃圾回收。

        Java、JavaScript、PHP、Python 等語言自動垃圾回收。

        JS中擁有自動的垃圾回收機制,會自動將這些垃圾對象從內存中銷毀,我們不需要也不能進行垃圾回收的操作。我們需要做的只是要將不再使用的對象設置為 null 即可。

        為什么需要垃圾回收

        • 在C / C++中,跟蹤內存的使用和管理內存對開發者來說是很大的負擔
          • JavaScript是使用垃圾回收機制的語言,也就是說執行環境負責在代碼執行時管理內存,幫開發者卸下了這個負擔
          • 通過自動內存管理實現內存的分配和資源的回收
          • 基本思路很簡單,確定哪個變量不會再被使用了,把它的內存空間釋放
          • 這個過程是周期性的,意思是這個垃圾回收程序每隔一段時間就會運行一次
        • 像JS中的對象、字符串、對象的內存是不固定的,只有真正用到的時候才會動態分配內存
          • 這些內存需在不使用后進行釋放以便再次使用,否則在計算機可用內存耗盡后造成崩潰
        • 瀏覽器發展史上的垃圾回收法主要有
          • 引用計數法
          • 標記清除法

        引用計數法

        思路

        • 變量只是對值進行引用
        • 當變量引用該值時,引用次數+1
        • 當該變量的引用被覆蓋或者清除時,引用次數-1
        • 當引用次數為0時,就可以安全地釋放這塊內存。
        let arr = [1, 0, 1]   // [1, 0, 1]這塊內存被arr引用  引用次數為1 arr = [0, 1, 0]  // [1, 0, 1]的內存引用次數為0被釋放                    // [0, 1, 0]的內存被arr引用   引用次數為1 const tmp = arr  // [0, 1, 0]的內存被tmp引用   引用次數為2

        循環引用問題

        Netscape Navigator 3.0 采用

        • 在這個例子中,ObjectA和ObjectB的屬性分別相互引用
        • 造成這個函數執行后,Object被引用的次數不會變成0,影響了正常的GC。
        • 如果執行多次,將造成嚴重的內存泄漏。
        • 而標記清除法則不會出現這個問題。
        function Example(){      let ObjectA = new Object();     let ObjectB = new Object();      ObjectA.p = ObjectB;     ObjectB.p = ObjectA;     }  Example();
        • 解決方法:在函數結束時將其指向null
        ObjectA = null; ObjectB = null;

        標記清除法

        為了解決循環引用造成的內存泄漏問題,Netscape Navigator 4.0 開始采用標記清除法

        到了 2008 年,IE、Firefox、Opera、Chrome 和 Safari 都在自己的 JavaScript 實現中采用標記清理(或 其變體),只是在運行垃圾回收的頻率上有所差異。

        思路

        • 在變量進入執行上下文時打上“進入”標記
        • 同時在變量離開執行上下文時也打上“離開”標記
          • 從此以后,無法訪問這個變量
          • 在下一次垃圾回收時進行內存的釋放
        function Example(n){     const a = 1, b = 2, c = 3;     return n * a * b * c; } // 標記Example進入執行上下文  const n = 1;  // 標記n進入執行上下文 Example(n);   // 標記a,b,c進入執行上下文 console.log(n); // 標記a, b, c離開執行上下文,等待垃圾回收

        const和let聲明提升性能

        • const和let不僅有助于改善代碼風格,同時有利于垃圾回收性能的提升
        • const和let使JS有了塊級作用域,當塊級作用域比函數作用域更早結束時,垃圾回收程序更早介入
        • 盡早回收該回收的內存,提升了垃圾回收的性能

        V8引擎的垃圾回收

        V8引擎的垃圾回收采用標記清除法與分代回收法

        分為新生代和老生代

        新生代

        新生代垃圾回收采用Scavenge 算法

        分配給常用內存和新分配的小量內存

        • 內存大小

          • 32位系統16M內存
          • 64位系統32M內存
        • 分區

          • 新生代內存分為以下兩區,內存各占一半
          • From space
          • To space
        • 運行

          • 實際運行的只有From space
          • To space處于空閑狀態
        • Scavenge算法

          • 當From space內存使用將要達到上限時開始垃圾回收,將From space中的不可達對象都打上標記
          • 將From space的未標記對象復制到To space。
            • 解決了內存散落分塊的問題(不連續的內存空間)
            • 相當于用空間換時間。
          • 然后清空From space、將其閑置,也就是轉變為To space,俗稱反轉。
        • 新生代 -> 老生代

          • 新生代存放的是新分配的小量內存,如果達到以下條件中的一個,將被分配至老生代
            • 內存大小達到From space的25%
            • 經歷了From space <-> To space的一個輪回

        javascript有gc嗎

        老生代

        老生代采用mark-sweep標記清除和mark-compact標記整理

        通常存放較大的內存塊和從新生代分配過來的內存塊

        • 內存大小
          • 32位系統700M左右
          • 64位系統1.4G左右
        • 分區
          • Old Object Space
            • 字面的老生代,存放的是新生代分配過來的內存。
          • Large Object Space
            • 存放其他區域放不下的較大的內存,基本都超過1M
          • Map Space
            • 存放存儲對象的映射關系
          • Code Space
            • 存儲編譯后的代碼
        • 回收流程
          • 標記分類(三色標記)
            • 未被掃描,可回收,下面簡稱1類
            • 掃描中,不可回收,下面簡稱2類
            • 掃描完成,不可回收,下面簡稱3類
          • 遍歷
            • 采用深度優先遍歷,遍歷每個對象。
            • 首先將非根部對象全部標記為1類,然后進行深度優先遍歷。
            • 遍歷過程中將對象壓入棧,這個過程中對象被標記為2類
            • 遍歷完成對象出棧,這個對象被標記為3類
            • 整個過程直至棧空
          • Mark-sweep
            • 標記完成之后,將標記為1類的對象進行內存釋放

        • javascript有gc嗎

        • Mark-compact

          • 垃圾回收完成之后,內存空間是不連續的。

          • 這樣容易造成無法分配較大的內存空間的問題,從而觸發垃圾回收。

          • 所以,會有Mark-compact步驟將未被回收的內存塊整理為連續地內存空間。

          • 頻繁觸發垃圾回收會影響引擎的性能,內存空間不足時也會優先觸發Mark-compact

        javascript有gc嗎

        垃圾回收優化

        • 增量標記
          • 如果用集中的一段時間進行垃圾回收,新生代倒還好,老生代如果遍歷較大的對象,可能會造成卡頓。
          • 增量標記:使垃圾回收程序和應用邏輯程序交替運行,思想類似Time Slicing
        • 并行回收
          • 在垃圾回收的過程中,開啟若干輔助線程,提高垃圾回收效率。
        • 并發回收
          • 在邏輯程序執行的過程中,開啟若干輔助線程進行垃圾回收,清理和主線程沒有任何邏輯關系的內存。

        內存泄露場景

        全局變量

        // exm1 function Example(){     exm = 'LeBron'    }  // exm2 function Example(){     this.exm = 'LeBron' } Example()

        未清除的定時器

        const timer = setInterval(() => {     //... }, 1000)  // clearInterval(timer)

        閉包

        function debounce(fn, time) {   let timeout = null;    return function () {     if (timeout) {       clearTimeout(timeout);     }      timeout = setTimeout(() => {       fn.apply(this, arguments);     }, time);   }; }  const fn = debounce(handler, 1000); // fn引用了timeout

        未清除的DOM元素引用

        const element = {     // 此處引用了DOM元素     button:document.getElementById('LeBron'),     select:document.getElementById('select') }  document.body.removeChild(document.getElementById('LeBron'))

        如何檢測內存泄漏

        這個其實不難,瀏覽器原帶的開發者工具Performance就可以

        • 步驟
          • F12打開開發者工具
          • 選擇Performance工具欄
          • 勾選屏幕截圖和Memory
          • 點擊開始錄制
          • 一段時間之后結束錄制
        • 結果
          • 堆內存會周期性地分配和釋放
          • 如果堆內存的min值在逐漸上升則存在內存泄漏

        javascript有gc嗎

        優化內存使用

        1、盡量不在for循環中定義函數

        // exm const fn = (idx) => {     return idx * 2; }  function Example(){     for(let i=0;i<1000;i++){         //const fn = (idx) => {         //    return idx * 2;         // }         const res = fn(i);     } }

        2、盡量不在for循環中定義對象

        function Example() {   const obj = {};   let res = "";   for (let i = 0; i < 1000; i++) {     // const obj = {     //   a: i,     //   b: i * 2,     //   c: i * 3,     // };     obj.a = i;     obj.b = i * 2;     obj.c = i * 3;     res += JSON.stringify(obj);   }   return res }

        3、清空數組

        arr = [0, 1, 2] arr.length = 0; // 清空了數組,數組類型不變 // arr = []  // 重新申請了一塊空數組對象內存

        【推薦學習:javascript高級教程】

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 国产成人久久精品一区二区三区 | 99re只有精品8中文| 拍国产真实乱人偷精品| 亚洲欧美日韩精品久久| 精品亚洲成AV人在线观看| 日本精品一区二区三区四区| 99久久精品国产一区二区蜜芽| 精品午夜福利在线观看| 在线观看亚洲精品福利片| 精品无码久久久久久久久久| 一区二区三区四区精品视频| 国产亚洲精品xxx| 成人区人妻精品一区二区不卡视频| 亚洲日韩国产精品乱| 人妻VA精品VA欧美VA| 精品91自产拍在线观看| 国产精品1024视频| 杨幂国产精品福利在线观看| 久久99热国产这有精品| 精品四虎免费观看国产高清午夜| 国精品午夜福利视频不卡| 热re99久久精品国99热| 亚洲色精品aⅴ一区区三区| 亚洲人成国产精品无码| 亚洲乱码精品久久久久..| 亚洲精品天堂成人片?V在线播放| 久久91这里精品国产2020| 久久久人妻精品无码一区| 精品露脸国产偷人在视频| 九色精品视频在线观看| 欧美精品免费专区在线观看| 久久精品国产秦先生| 久久九九精品99国产精品| 午夜国产精品无套| 国内精品伊人久久久久网站| 国产精品.XX视频.XXTV| 国产人成精品综合欧美成人| 国产亚洲精品线观看动态图| 国产欧美在线观看精品一区二区| 国产精品免费一区二区三区| 国产亚州精品女人久久久久久|