偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

閉包會(huì)造成內(nèi)存泄漏嗎?

開(kāi)發(fā) 前端
在談內(nèi)存泄漏這個(gè)問(wèn)題之前先看看JavaScript的垃圾收集機(jī)制,JavaScript 具有自動(dòng)垃圾收集機(jī)制,就是找出那些不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存。為此,垃圾收集器會(huì)按照固定的時(shí)間間隔(或代碼執(zhí)行中預(yù)定的收集時(shí)間)。常用的的方法有兩種,即標(biāo)記清楚和引用計(jì)數(shù)。

[[174907]]

前言

在談內(nèi)存泄漏這個(gè)問(wèn)題之前先看看JavaScript的垃圾收集機(jī)制,JavaScript 具有自動(dòng)垃圾收集機(jī)制,就是找出那些不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存。為此,垃圾收集器會(huì)按照固定的時(shí)間間隔(或代碼執(zhí)行中預(yù)定的收集時(shí)間)。常用的的方法有兩種,即標(biāo)記清楚和引用計(jì)數(shù)。

1. 標(biāo)記清除

JavaScript 中最常用的垃圾收集方式是標(biāo)記清除(mark-and-sweep)。垃圾收集器在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記(可以使用任何標(biāo)記方式)。然后,它會(huì)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無(wú)法訪問(wèn)到這些變量了。***,垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值并回收它們所占用的內(nèi)存空間。

2. 引用計(jì)數(shù)

引用計(jì)數(shù)(reference counting)的含義是跟蹤記錄每個(gè)值被引用的次數(shù)。當(dāng)聲明了一個(gè)變量并將一個(gè)引用類型值賦給該變量時(shí),則這個(gè)值的引用次數(shù)就是1。如果同一個(gè)值又被賦給另一個(gè)變量,則該值的引用次數(shù)加1。相反,如果包含對(duì)這個(gè)值引用的變量又取得了另外一個(gè)值,則這個(gè)值的引用次數(shù)減1。當(dāng)這個(gè)值的引用次數(shù)變成0 時(shí),則說(shuō)明沒(méi)有辦法再訪問(wèn)這個(gè)值了,因而就可以將其占用的內(nèi)存空間回收回來(lái)。這樣,當(dāng)垃圾收集器下次再運(yùn)行時(shí),它就會(huì)釋放那些引用次數(shù)為零的值所占用的內(nèi)存。

Netscape Navigator 3.0 是最早使用引用計(jì)數(shù)策略的瀏覽器,但很快它就遇到了一個(gè)嚴(yán)重的問(wèn)題,請(qǐng)看下面這個(gè)例子:

  1. function problem(){ 
  2.     var objectA = new Object(); 
  3.     var objectB = new Object(); 
  4.     objectA.someOtherObject = objectB; 
  5.     objectB.anotherObject = objectA; 
  6.  

說(shuō)明:objectA 和objectB 通過(guò)各自的屬性相互引用,即這兩個(gè)對(duì)象的引用次數(shù)都是2,在采用標(biāo)記清除策略的實(shí)現(xiàn)中,由于函數(shù)執(zhí)行之后,這兩個(gè)對(duì)象都離開(kāi)了作用域,因此這種相互引用不是個(gè)問(wèn)題。但在采用引用計(jì)數(shù)策略的實(shí)現(xiàn)中,當(dāng)函數(shù)執(zhí)行完畢后,objectA 和objectB 還說(shuō)明將繼續(xù)存在,因?yàn)樗鼈兊囊么螖?shù)永遠(yuǎn)不會(huì)是0。假如這個(gè)函數(shù)被重復(fù)多次調(diào)用,就會(huì)導(dǎo)致大量?jī)?nèi)存得不到回收。

為此,Netscape 在Navigator 4.0 中放棄了引用計(jì)數(shù)方式,然而引用計(jì)數(shù)導(dǎo)致的麻煩并未就此了結(jié)。IE9以前中有一部分對(duì)象并不是原生JavaScript 對(duì)象。例如,其BOM 和DOM 中的對(duì)象就是使用C++以COM(Component Object Model,組件對(duì)象模型)對(duì)象的形式實(shí)現(xiàn)的,而COM 對(duì)象的垃圾收集機(jī)制采用的就是引用計(jì)數(shù)策略。因此,即使IE 的JavaScript 引擎是使用標(biāo)記清除策略來(lái)實(shí)現(xiàn)的,但JavaScript 訪問(wèn)的COM 對(duì)象依然是基于引用計(jì)數(shù)策略的。換句話說(shuō),只要在IE 中涉及COM 對(duì)象,就會(huì)存在循環(huán)引用的問(wèn)題。

比如:

  1. var element = document.getElementById("some_element"); 
  2. var myObject = new Object(); 
  3. myObject.element = element; 
  4. element.someObject = myObject;  

DOM 元素(element)與一個(gè)原生JavaScript 對(duì)象(myObject)之間創(chuàng)建了循環(huán)引用。其中,變量myObject 有一個(gè)名為element 的屬性指向element 對(duì)象;而變量element 也有一個(gè)屬性名叫someObject 回指myObject。由于存在這個(gè)循環(huán)引用,即使將例子中的DOM 從頁(yè)面中移除,它也永遠(yuǎn)不會(huì)被回收。

解決辦法:將變量設(shè)為null從而切斷變量與它此前引用的值之間的連接。

  1. myObject.element = null
  2.  
  3. element.someObject = null 

看完上面的內(nèi)容,我來(lái)談?wù)}。

閉包不會(huì)引起內(nèi)存泄漏

由于IE9 之前的版本對(duì)JScript 對(duì)象和COM 對(duì)象使用不同的垃圾收集。因此閉包在IE 的這些版本中會(huì)導(dǎo)致一些特殊的問(wèn)題。具體來(lái)說(shuō),如果閉包的作用域鏈中保存著一個(gè)HTML 元素,那么就意味著該元素將無(wú)法被銷毀請(qǐng)看例子:

  1. function assignHandler(){ 
  2.     var element = document.getElementById("someElement"); 
  3.     element.onclick = function(){ 
  4.         alert(element.id); 
  5.     }; 
  6.  

以上代碼創(chuàng)建了一個(gè)作為element 元素事件處理程序的閉包,而這個(gè)閉包則又創(chuàng)建了一個(gè)循環(huán)引用。由于匿名函數(shù)保存了一個(gè)對(duì)assignHandler()的活動(dòng)對(duì)象的引用,因此就會(huì)導(dǎo)致無(wú)法減少element 的引用數(shù)。只要匿名函數(shù)存在,element 的引用數(shù)至少也是1,因此它所占用的內(nèi)存就永遠(yuǎn)不會(huì)被回收

解決辦法前言已經(jīng)提到過(guò),把element.id 的一個(gè)副本保存在一個(gè)變量中,從而消除閉包中該變量的循環(huán)引用同時(shí)將element變量設(shè)為null。

  1. function assignHandler(){ 
  2.     var element = document.getElementById("someElement"); 
  3.     var id = element.id; 
  4.     element.onclick = function(){ 
  5.         alert(id); 
  6.     }; 
  7.     element = null
  8.  

總結(jié):閉包并不會(huì)引起內(nèi)存泄漏,只是由于IE9之前的版本對(duì)JScript對(duì)象和COM對(duì)象使用不同的垃圾收集,從而導(dǎo)致內(nèi)存無(wú)法進(jìn)行回收,這是IE的問(wèn)題,所以閉包和內(nèi)存泄漏沒(méi)半毛錢(qián)關(guān)系。

這篇文章里做了詳細(xì)的測(cè)試,有興趣的可以點(diǎn)擊查看

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2022-05-09 14:09:23

多線程線程安全

2021-03-07 17:17:07

Java內(nèi)存閉包

2025-04-01 05:22:00

JavaThread變量

2015-08-18 13:42:42

js作用域鏈變量

2024-01-22 09:51:32

Swift閉包表達(dá)式尾隨閉包

2022-04-07 07:41:18

String字符串內(nèi)存泄漏

2021-06-02 07:57:48

內(nèi)存管理

2023-07-11 08:46:38

閉包函數(shù)Rust

2024-03-11 08:22:40

Java內(nèi)存泄漏

2023-12-18 10:45:23

內(nèi)存泄漏計(jì)算機(jī)服務(wù)器

2021-02-21 16:21:19

JavaScript閉包前端

2012-02-22 21:28:58

內(nèi)存泄漏

2017-03-09 10:45:31

定義內(nèi)存泄漏

2025-02-11 08:00:00

閉包JavaScript開(kāi)發(fā)

2019-07-17 15:45:24

Spark內(nèi)存Java

2023-01-09 08:00:41

JavaScript閉包

2024-11-26 00:45:29

free區(qū)域字段

2021-01-22 07:48:07

JavaScript 高階函數(shù)閉包

2015-03-30 11:18:50

內(nèi)存管理Android

2021-08-09 09:54:37

內(nèi)存泄漏JS 阿里云
點(diǎn)贊
收藏

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