<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【W(wǎng)eb技術(shù)】849- 前端常見(jiàn)內(nèi)存泄漏及解決方案

          共 3531字,需瀏覽 8分鐘

           ·

          2021-01-27 10:02

          作者:lzg9527
          https://juejin.cn/post/6914092198170460168

          最近收到測(cè)試人員的反饋說(shuō)我們開(kāi)發(fā)的頁(yè)面偶現(xiàn)卡死,點(diǎn)擊無(wú)反應(yīng)的情況,特別是打開(kāi)頁(yè)面較久的時(shí)候發(fā)生概率較高。打開(kāi)任務(wù)管理器,看到內(nèi)存占有率已經(jīng)很高了,初步判斷可能存在內(nèi)存泄漏的情況。下面排查內(nèi)存泄漏的原因。

          系統(tǒng)進(jìn)程不再用到的內(nèi)存,沒(méi)有及時(shí)釋放,就叫做內(nèi)存泄漏(memory leak)。當(dāng)內(nèi)存占用越來(lái)越高,輕則影響系統(tǒng)性能,重則導(dǎo)致進(jìn)程崩潰。Chrome 限制了瀏覽器所能使用的內(nèi)存極限(64 位為 1.4GB,32 位為 1.0GB)

          引起內(nèi)存泄漏的原因

          意外的全局變量

          由于 js 對(duì)未聲明變量的處理方式是在全局對(duì)象上創(chuàng)建該變量的引用。如果在瀏覽器中,全局對(duì)象就是 window 對(duì)象。變量在窗口關(guān)閉或重新刷新頁(yè)面之前都不會(huì)被釋放,如果未聲明的變量緩存大量的數(shù)據(jù),就會(huì)導(dǎo)致內(nèi)存泄露。

          • 未聲明變量
          function?fn()?{
          ??a?=?'global?variable'
          }
          fn()
          • 使用 this 創(chuàng)建的變量(this 的指向是 window)。
          function?fn()?{
          ??this.a?=?'global?variable'
          }
          fn()

          解決方法:

          • 避免創(chuàng)建全局變量
          • 使用嚴(yán)格模式,在 JavaScript 文件頭部或者函數(shù)的頂部加上 use strict

          閉包引起的內(nèi)存泄漏

          原因:閉包可以讀取函數(shù)內(nèi)部的變量,然后讓這些變量始終保存在內(nèi)存中。如果在使用結(jié)束后沒(méi)有將局部變量清除,就可能導(dǎo)致內(nèi)存泄露。

          function?fn?()?{
          ??var?a?=?"I'm?a";
          ??return?function?()?{
          ????console.log(a);
          ??};
          }

          解決:將事件處理函數(shù)定義在外部,解除閉包,或者在定義事件處理函數(shù)的外部函數(shù)中。

          比如:在循環(huán)中的函數(shù)表達(dá)式,能復(fù)用最好放到循環(huán)外面。

          //?bad
          for?(var?k?=?0;?k?10;?k++)?{
          ??var?t?=?function?(a)?{
          ????//?創(chuàng)建了10次??函數(shù)對(duì)象。
          ????console.log(a)
          ??}
          ??t(k)
          }

          //?good
          function?t(a)?{
          ??console.log(a)
          }
          for?(var?k?=?0;?k?10;?k++)?{
          ??t(k)
          }
          t?=?null

          沒(méi)有清理的 DOM 元素引用

          原因:雖然別的地方刪除了,但是對(duì)象中還存在對(duì) dom 的引用。

          //?在對(duì)象中引用DOM
          var?elements?=?{
          ??btn:?document.getElementById('btn'),
          }
          function?doSomeThing()?{
          ??elements.btn.click()
          }

          function?removeBtn()?{
          ??//?將body中的btn移除,?也就是移除?DOM樹(shù)中的btn
          ??document.body.removeChild(document.getElementById('button'))
          ??//?但是此時(shí)全局變量elements還是保留了對(duì)btn的引用,?btn還是存在于內(nèi)存中,不能被GC回收
          }

          解決方法:手動(dòng)刪除,elements.btn = null

          被遺忘的定時(shí)器或者回調(diào)

          定時(shí)器中有 dom 的引用,即使 dom 刪除了,但是定時(shí)器還在,所以?xún)?nèi)存中還是有這個(gè) dom。

          //?定時(shí)器
          var?serverData?=?loadData()
          setInterval(function?()?{
          ??var?renderer?=?document.getElementById('renderer')
          ??if?(renderer)?{
          ????renderer.innerHTML?=?JSON.stringify(serverData)
          ??}
          },?5000)

          //?觀察者模式
          var?btn?=?document.getElementById('btn')
          function?onClick(element)?{
          ??element.innerHTMl?=?"I'm?innerHTML"
          }
          btn.addEventListener('click',?onClick)

          解決方法:

          • 手動(dòng)刪除定時(shí)器和 dom。
          • removeEventListener 移除事件監(jiān)聽(tīng)

          vue 中容易出現(xiàn)內(nèi)存泄露的幾種情況

          在 Vue SPA 開(kāi)發(fā)應(yīng)用,那么就更要當(dāng)心內(nèi)存泄漏的問(wèn)題。因?yàn)樵?SPA 的設(shè)計(jì)中,用戶(hù)使用它時(shí)是不需要刷新瀏覽器的,所以 JavaScript 應(yīng)用需要自行清理組件來(lái)確保垃圾回收以預(yù)期的方式生效。因此開(kāi)發(fā)過(guò)程中,你需要時(shí)刻警惕內(nèi)存泄漏的問(wèn)題。

          全局變量造成的內(nèi)存泄露

          聲明的全局變量在切換頁(yè)面的時(shí)候沒(méi)有清空

          <template>
          ??<div?id="home">這里是首頁(yè)div>
          template>
          
          
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    建筑偷拍网 | 91免费在线视频 | 欧美孕妇一级片 | 国产熟妇XXXXXⅩ性Ⅹ交 | 国产特级乱浽片AA片 |