日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
前端進(jìn)階之深入了解JS垃圾回收機(jī)制和內(nèi)存泄漏

本文轉(zhuǎn)載自微信公眾號「Android開發(fā)編程」,作者Android開發(fā)編程。轉(zhuǎn)載本文請聯(lián)系A(chǔ)ndroid開發(fā)編程公眾號。

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比亭湖網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式亭湖網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋亭湖地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。

前言

JS自帶一套內(nèi)存管理引擎,負(fù)責(zé)創(chuàng)建對象、銷毀對象,以及垃圾回收。

我們來探討一下垃圾回收機(jī)制和內(nèi)存泄露;

一、垃圾回收機(jī)制詳解

1、什么是js的回收機(jī)制

  • 垃圾回收機(jī)制的原理是找到不再繼續(xù)使用的變量,釋放其內(nèi)存。垃圾回收器會按照固定的時(shí)間間隔(或代碼中預(yù)定的收集時(shí)間),周期性地執(zhí)行這一操作;
  • Javascript 會找出不再使用的變量,不再使用意味著這個(gè)變量生命周期的結(jié)束。Javascript 中存在兩種變量——全局變量和局部變量,全部變量的聲明周期會一直持續(xù),直到頁面卸載;
  • 而局部變量聲明在函數(shù)中,它的聲明周期從執(zhí)行函數(shù)開始,直到函數(shù)執(zhí)行結(jié)束。在這個(gè)過程中,局部變量會在堆或棧上被分配相應(yīng)的空間以存儲它們的值,函數(shù)執(zhí)行結(jié)束,這些局部變量也不再被使用,它們所占用的空間也就被釋放;
  • 垃圾回收的兩種實(shí)現(xiàn)方式:標(biāo)記清除、引用計(jì)數(shù)

2、標(biāo)記清除(主流瀏覽器做法)

  • 主要思想是給當(dāng)前不使用的值加上標(biāo)記,然后再回收他的內(nèi)存;
  • 垃圾回收器在運(yùn)行時(shí)會給存儲在內(nèi)存中的變量加上標(biāo)記,然后他會去掉環(huán)境變量和被環(huán)境變量引用的變量的標(biāo)記,此后被加上標(biāo)記的變量(環(huán)境變量中沒有使用訪問的變量)就是準(zhǔn)備刪除的變量;最后垃圾回收器完成清除工作,銷毀那些帶標(biāo)記的值,并回收他們占用的內(nèi)存空間;

標(biāo)記和掃描算法經(jīng)過:

  • 根節(jié)點(diǎn):一般來說,根是代碼中引用的全局變量;
  • 然后算法檢查所有根節(jié)點(diǎn)和他們的子節(jié)點(diǎn)并且把他們標(biāo)記為活躍的(意思是他們不是垃圾)。任何根節(jié)點(diǎn)不能訪問的變量將被標(biāo)記為垃圾;
  • 最后,垃圾收集器釋放所有未被標(biāo)記為活躍的內(nèi)存塊,并將這些內(nèi)存返回給操作系統(tǒng);

3、引用計(jì)數(shù)(IE9以下)

含義是跟蹤記錄所有值被引用的次數(shù);

例如變量a賦值后,這個(gè)值的引用次數(shù)為1,這個(gè)a值又被賦值給另一個(gè)變量b,這時(shí)引用次數(shù)+1;但當(dāng)b賦另外的值,引用次數(shù)-1;當(dāng)值的引用書為0,說明沒有辦法再訪問這個(gè)值,這時(shí)就可以將內(nèi)存回收了。

IE9以下還在使用引用計(jì)數(shù),當(dāng)對象循環(huán)引用時(shí),引用次數(shù)無法標(biāo)記為0,就會導(dǎo)致無法被回收。其他瀏覽器廢棄使用;

下面的代碼

 
 
 
 
  1. var o1 = { 
  2.   o2: { 
  3.     x: 1 
  4.   } 
  5. }; 
  6. // 兩個(gè)對象被創(chuàng)建。 
  7. // ‘o1’對象引用‘o2’對象作為其屬性。 
  8. // 不可以被垃圾收集 
  9. var o3 = o1; // ‘o3’變量是第二個(gè)引用‘o1‘指向的對象的變量.  
  10. o1 = 1;      // 現(xiàn)在,在‘o1’中的對象只有一個(gè)引用,由‘o3’變量表示 
  11. var o4 = o3.o2; // 對象的‘o2’屬性的引用. 
  12.                 // 此對象現(xiàn)在有兩個(gè)引用:一個(gè)作為屬性、另一個(gè)作為’o4‘變量 
  13. o3 = '374'; // 原來在“o1”中的對象現(xiàn)在為零,對它的引用可以垃圾收集。 
  14.             // 但是,它的‘o2’屬性存在,由‘o4’變量引用,因此不能被釋放。 
  15. o4 = null; // ‘o1’中最初對象的‘o2’屬性對它的引用為零。它可以被垃圾收集。 

二、Js常見的內(nèi)存泄漏

內(nèi)存泄漏是應(yīng)用程序過去使用,但不再需要的尚未返回到操作系統(tǒng)或可用內(nèi)存池的內(nèi)存片段。由于沒有被釋放而導(dǎo)致的,它將可能引起程序的卡頓和崩潰;

1、意外的全局變量

 
 
 
 
  1. function foo(arg) { 
  2.     bar = "test"; 
  3.     // window.bar = "test"; 

js對未聲明變量會在全局最高對象上創(chuàng)建它的引用,(是以屬性存在的,而不是變量),如果在游覽器上就是window對象,如果在node環(huán)境下就是global;如果未聲明的變量緩存大量的數(shù)據(jù),它可能只有在頁面被刷新或者被關(guān)閉的時(shí)候才會釋放內(nèi)存,這樣就造成了內(nèi)存意外泄漏;

2、被忘記的定時(shí)器或者回調(diào)函數(shù)

我們以經(jīng)常在 JavaScript 中使用的 setInterval 為例;

 
 
 
 
  1. var serverData = loadData(); 
  2. setInterval(function() { 
  3.     var renderer = document.getElementById('renderer'); 
  4.     if(renderer) { 
  5.         renderer.innerHTML = JSON.stringify(serverData); 
  6.     } 
  7. }, 5000); //每5秒執(zhí)行一次. 
  • 上面的代碼片段顯示了使用定時(shí)器引用節(jié)點(diǎn)或無用數(shù)據(jù)的后果。它既不會被收集,也不會被釋放。無法被垃圾收集器收集,頻繁的被調(diào)用,占用內(nèi)存;
  • 而正確的使用方法是,確保一旦依賴于它們的事件已經(jīng)處理完成,就通過明確的調(diào)用來刪除它們;

3、閉包

  • 閉包是一個(gè)函數(shù)A返回一個(gè)內(nèi)聯(lián)的函數(shù)B,及時(shí)A函數(shù)執(zhí)行完函數(shù)B也可以訪問函數(shù)A里面的變量,這就是一個(gè)簡單的閉包;
  • 本質(zhì)上閉包是將函數(shù)內(nèi)部和外部連接起來的一座橋梁;
 
 
 
 
  1. function my(name) { 
  2.     function sendName() { 
  3.         console.log(name) 
  4.     } 
  5.     return sendName 
  6. var test=my("test") 
  7. test()  //test 

在my()內(nèi)部創(chuàng)建的sendName()函數(shù)是不會被回收的,因?yàn)樗蝗肿兞縯est引用,處于隨時(shí)被調(diào)用的狀態(tài)。如果向釋放內(nèi)存可以設(shè)置test=null;由于閉包會攜帶包含它的函數(shù)的作用域,因此會比其他函數(shù)占用更多的內(nèi)存。過度使用閉包可能會導(dǎo)致內(nèi)存占用過多

4、DOM泄漏

  • 瀏覽器中DOM和js采用的是不一樣的引擎,DOM采用的是渲染引擎,而js采用的是v8引擎,所以在用js操作DOM時(shí)會比較耗費(fèi)性能,因?yàn)樗麄冃枰獦騺礞溄铀麄?。為了減少DOM的操作,我們一般將常用的DOM;
  • 我們會采用變量引用的方式會將其緩存在當(dāng)前環(huán)境。如果在進(jìn)行一些刪除、更新操作之后,可能會忘記釋放已經(jīng)緩存的DOM;
 
 
 
 
  1. var elements = { 
  2.     button: document.getElementById('button'), 
  3.     image: document.getElementById('image') 
  4. }; 
  5. function doStuff() { 
  6.     elements.image.src = 'http://test.png'; 
  7. function removeImage() { 
  8.     // image 元素是body的直接子元素。 
  9.     document.body.removeChild(document.getElementById('image')); 
  10.     // 我們?nèi)匀豢梢栽谌衷貙ο笾幸胋utton。換句話說,button元素仍在內(nèi)存中,無法由GC收集 

總結(jié)

GC機(jī)制是自動完成的,但我們可以強(qiáng)制啟動它,或是關(guān)閉它;

我們在開發(fā)中要注意內(nèi)存泄露問題,不然會出現(xiàn)意想不到的情況;

一起學(xué)習(xí)加油;


文章名稱:前端進(jìn)階之深入了解JS垃圾回收機(jī)制和內(nèi)存泄漏
地址分享:http://www.dlmjj.cn/article/coshpsc.html