自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JS高程中的垃圾回收機(jī)制與常見內(nèi)存泄露的解決方法

存儲(chǔ) 存儲(chǔ)軟件
在C和C++之類的語言中,需要手動(dòng)來管理內(nèi)存的,這也是造成許多不必要問題的根源。幸運(yùn)的是,在編寫js的過程中,內(nèi)存的分配以及內(nèi)存的回收完全實(shí)現(xiàn)了自動(dòng)管理,我們不用操心這種事情。

內(nèi)存的生命周期:

  1. 分配你所需要的內(nèi)存:
  2. 由于字符串、對(duì)象等沒有固定的大小,js程序在每次創(chuàng)建字符串、對(duì)象的時(shí)候,程序都會(huì)分配內(nèi)存來存儲(chǔ)那個(gè)實(shí)體。
  3. 使用分配到的內(nèi)存做點(diǎn)什么。

不需要時(shí)將其釋放回歸:

在不需要字符串、對(duì)象的時(shí)候,需要釋放其所占用的內(nèi)存,否則將會(huì)消耗完系統(tǒng)中所有可用的內(nèi)存,造成系統(tǒng)崩潰,這就是垃圾回收機(jī)制所存在的意義。

所謂的內(nèi)存泄漏指的是:由于疏忽或錯(cuò)誤造成程序未能釋放那些已經(jīng)不再使用的內(nèi)存,造成內(nèi)存的浪費(fèi)。

[[236748]]

垃圾回收機(jī)制:

在C和C++之類的語言中,需要手動(dòng)來管理內(nèi)存的,這也是造成許多不必要問題的根源。幸運(yùn)的是,在編寫js的過程中,內(nèi)存的分配以及內(nèi)存的回收完全實(shí)現(xiàn)了自動(dòng)管理,我們不用操心這種事情。

垃圾收集機(jī)制的原理:

垃圾收集器會(huì)按照固定的時(shí)間間隔,周期性的找出不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存。

什么叫不再繼續(xù)使用的變量?

不再使用的變量也就是生命周期結(jié)束的變量,是局部變量,局部變量只在函數(shù)的執(zhí)行過程中存在,當(dāng)函數(shù)運(yùn)行結(jié)束,沒有其他引用(閉包),那么該變量會(huì)被標(biāo)記回收。

全局變量的生命周期直至瀏覽器卸載頁面才會(huì)結(jié)束,也就是說全局變量不會(huì)被當(dāng)成垃圾回收。

標(biāo)記清除:當(dāng)前采用的垃圾收集策略

工作原理:

當(dāng)變量進(jìn)入環(huán)境時(shí)(例如在函數(shù)中聲明一個(gè)變量),將這個(gè)變量標(biāo)記為“進(jìn)入環(huán)境”,當(dāng)變量離開環(huán)境時(shí),則將其標(biāo)記為“離開環(huán)境”。標(biāo)記“離開環(huán)境”的就回收內(nèi)存。

工作流程:

  1. 垃圾收集器會(huì)在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。
  2. 去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記。
  3. 那些還存在標(biāo)記的變量被視為準(zhǔn)備刪除的變量。
  4. ***垃圾收集器會(huì)執(zhí)行***一步內(nèi)存清除的工作,銷毀那些帶標(biāo)記的值并回收它們所占用的內(nèi)存空間。

到2008年為止,IE、Chorme、Fireofx、Safari、Opera 都使用標(biāo)記清除式的垃圾收集策略,只不過垃圾收集的時(shí)間間隔互有不同。

引用計(jì)數(shù)略:被廢棄的垃圾收集策

循環(huán)引用:跟蹤記錄每個(gè)值被引用的技術(shù)

在老版本的瀏覽器中(對(duì),又是IE),IE9以下BOM和DOM對(duì)象就是使用C++以COM對(duì)象的形式實(shí)現(xiàn)的。

COM的垃圾收集機(jī)制采用的就是引用計(jì)數(shù)策略,這種機(jī)制在出現(xiàn)循環(huán)引用的時(shí)候永遠(yuǎn)都釋放不掉內(nèi)存。

  1. var element = document.getElementById('something'); 
  2. var myObject = new Object(); 
  3. myObject.element = element; // element屬性指向dom 
  4. element.someThing = myObject; // someThing回指myObject 出現(xiàn)循環(huán)引用(兩個(gè)對(duì)象一直互相包含 一直存在計(jì)數(shù))。 

解決方式是,當(dāng)我們不使用它們的時(shí)候,手動(dòng)切斷鏈接:

  1. myObject.element = null;  
  2. element.someThing = null

淘汰:

IE9把BOM和DOM對(duì)象轉(zhuǎn)為了真正的js對(duì)象,避免了使用這種垃圾收集策略,消除了IE9以下常見的內(nèi)存泄漏的主要原因。

IE7以下有一個(gè)聲明狼藉的性能問題,大家了解一下:

  1. 256個(gè)變量,4096個(gè)對(duì)象(或數(shù)組)字面或者64KB的字符串,達(dá)到任何一個(gè)臨界值會(huì)觸發(fā)垃圾收集器運(yùn)行。
  2. 如果一個(gè)js腳本的生命周期一直保有那么多變量,垃圾收集器會(huì)一直頻繁的運(yùn)行,引發(fā)嚴(yán)重的性能問題。

IE7已修復(fù)這個(gè)問題。

哪些情況會(huì)引起內(nèi)存泄漏?

雖然有垃圾回收機(jī)制,但我們在編寫代碼的時(shí)候,有些情況還是會(huì)造成內(nèi)存泄漏,了解這些情況,并在編寫程序的時(shí)候,注意避免,我們的程序會(huì)更具健壯性。

意外的全局變量:

上文我們提到了全局變量不會(huì)被當(dāng)成垃圾回收,我們在編碼中有時(shí)會(huì)出現(xiàn)下面這種情況:

  1. function foo() { 
  2. this.bar2 = '默認(rèn)綁定this指向全局' // 全局變量=> window.bar2 
  3.  bar = '全局變量'; // 沒有聲明變量 實(shí)際上是全局變量=>window.bar 
  4. foo(); 

當(dāng)我們使用默認(rèn)綁定,this會(huì)指向全局,this.something也會(huì)創(chuàng)建一個(gè)全局變量,這一點(diǎn)可能很多人沒有注意到。

解決方法:在函數(shù)內(nèi)使用嚴(yán)格模式or細(xì)心一點(diǎn)

  1. function foo() { 
  2. "use strict";  
  3. this.bar2 = "嚴(yán)格模式下this指向undefined";  
  4. bar = "報(bào)錯(cuò)"
  5.  } 
  6.  foo(); 

當(dāng)然我們也可以手動(dòng)釋放全局變量的內(nèi)存:

  1. window.bar = undefined 
  2. delete window.bar2 

被遺忘的定時(shí)器和回調(diào)函數(shù)

當(dāng)不需要setInterval或者setTimeout時(shí),定時(shí)器沒有被clear,定時(shí)器的回調(diào)函數(shù)以及內(nèi)部依賴的變量都不能被回收,造成內(nèi)存泄漏。

  1. var someResource = getData(); 
  2. setInterval(function() { 
  3.     var node = document.getElementById('Node'); 
  4.     if(node) { 
  5.         node.innerHTML = JSON.stringify(someResource)); 
  6.         // 定時(shí)器也沒有清除 
  7.     } 
  8.     // node、someResource 存儲(chǔ)了大量數(shù)據(jù) 無法回收 
  9. }, 1000); 

解決方法: 在定時(shí)器完成工作的時(shí)候,手動(dòng)清除定時(shí)器。

閉包:

閉包可以維持函數(shù)內(nèi)局部變量,使其得不到釋放,造成內(nèi)存泄漏。

  1. function bindEvent() { 
  2.   var obj = document.createElement("XXX"); 
  3.   var unused = function () { 
  4.       console.log(obj,'閉包內(nèi)引用obj obj不會(huì)被釋放'); 
  5.   }; 
  6.   // obj = null

解決方法:手動(dòng)解除引用,obj = null。

循環(huán)引用問題

就是IE9以下的循環(huán)引用問題,上文講過了。

沒有清理DOM元素引用:

  1.  var refA = document.getElementById('refA'); 
  2. document.body.removeChild(refA); // dom刪除了 
  3. console.log(refA, "refA");  // 但是還存在引用 能console出整個(gè)div 沒有被回收 

不信的話,可以看下這個(gè)dom。

解決辦法:refA = null;

console保存大量數(shù)據(jù)在內(nèi)存中。

過多的console,比如定時(shí)器的console會(huì)導(dǎo)致瀏覽器卡死。

解決:合理利用console,線上項(xiàng)目盡量少的使用console,當(dāng)然如果你要發(fā)招聘,除外。

如何避免內(nèi)存泄漏:

記住一個(gè)原則:不用的東西,及時(shí)歸還,畢竟你是'借的'嘛。

減少不必要的全局變量,使用嚴(yán)格模式避免意外創(chuàng)建全局變量。

在你使用完數(shù)據(jù)后,及時(shí)解除引用(閉包中的變量,dom引用,定時(shí)器清除)。

組織好你的邏輯,避免死循環(huán)等造成瀏覽器卡頓,崩潰的問題。

關(guān)于內(nèi)存泄漏:

即使是1byte的內(nèi)存,也叫內(nèi)存泄漏,并不一定是導(dǎo)致瀏覽器崩潰、卡頓才能叫做內(nèi)存泄漏。

一般是堆區(qū)內(nèi)存泄漏,棧區(qū)不會(huì)泄漏。

基本類型的值存在內(nèi)存中,被保存在棧內(nèi)存中,引用類型的值是對(duì)象,保存在堆內(nèi)存中。所以對(duì)象、數(shù)組之類的,才會(huì)發(fā)生內(nèi)存泄漏。

使用chorme監(jiān)控內(nèi)存泄漏,可以看一下這篇文章

結(jié)語

了解了內(nèi)存泄漏的原因以及出現(xiàn)的情況,那么我們在編碼過程中只要多加注意,就不會(huì)發(fā)生非常嚴(yán)重的內(nèi)存泄漏問題。

責(zé)任編輯:武曉燕 來源: OBKoro1的學(xué)習(xí)分享
相關(guān)推薦

2017-06-12 17:38:32

Python垃圾回收引用

2009-12-09 17:28:34

PHP垃圾回收機(jī)制

2011-07-04 16:48:56

JAVA垃圾回收機(jī)制GC

2010-09-26 16:42:04

JVM內(nèi)存組成JVM垃圾回收

2023-02-28 07:56:07

V8內(nèi)存管理

2013-04-01 10:07:19

Java內(nèi)存回收機(jī)制

2009-06-23 14:15:00

Java垃圾回收

2024-02-22 17:15:22

JS垃圾回收機(jī)制

2021-12-07 08:01:33

Javascript 垃圾回收機(jī)制前端

2010-10-13 10:24:38

垃圾回收機(jī)制JVMJava

2011-06-28 10:19:40

C#開發(fā)

2010-09-25 15:33:19

JVM垃圾回收

2017-03-03 09:26:48

PHP垃圾回收機(jī)制

2017-08-17 15:40:08

大數(shù)據(jù)Python垃圾回收機(jī)制

2023-03-26 22:48:46

Python引用計(jì)數(shù)內(nèi)存

2024-10-28 13:18:54

2011-06-16 10:27:55

.NET內(nèi)存泄漏

2017-02-21 16:40:16

Android垃圾回收內(nèi)存泄露

2011-06-28 12:39:34

Java垃圾回收

2015-06-04 09:38:39

Java垃圾回收機(jī)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)