技術(shù)頻道導(dǎo)航
HTML/CSS
.NET技術(shù)
IIS技術(shù)
PHP技術(shù)
Js/JQuery
Photoshop
Fireworks
服務(wù)器技術(shù)
操作系統(tǒng)
網(wǎng)站運(yùn)營

贊助商

分類目錄

贊助商

最新文章

搜索

[實(shí)例]分析JS閉包如何導(dǎo)致內(nèi)存泄漏以及如何防止它

作者:admin    時(shí)間:2022-6-3 14:48:32    瀏覽:

閉包一個(gè)強(qiáng)大優(yōu)勢是內(nèi)部函數(shù)可以訪問外部函數(shù)的變量,但是也正是這一個(gè)特征,讓閉包容易產(chǎn)生內(nèi)存泄露的負(fù)面影響。

Javascript 允許嵌套函數(shù)(函數(shù)中的函數(shù))訪問父函數(shù)的變量,內(nèi)部函數(shù)訪問外部函數(shù)變量的過程稱為閉包。

但是一旦一個(gè)變量被任何閉包使用,它就會(huì)在該范圍內(nèi)所有閉包共享的詞法環(huán)境中結(jié)束,這可能導(dǎo)致內(nèi)存泄漏。

分析JS閉包如何導(dǎo)致內(nèi)存泄漏以及如何防止它

示例

<html>
<body>
<script>
   function parentFunction(arg1) {
      var a = arg1;
      return function childFunction (arg2) {
       alert( a +" "+ arg2);
    };
   };
   var val = parentFunction("outer val");
   val("inner val");
</script>
</body>
</html>

demodownload

執(zhí)行結(jié)果

在該示例中,“childFunction”是在“parentFunction”外部函數(shù)中定義的內(nèi)部函數(shù)。當(dāng)使用參數(shù)“outer val”調(diào)用'parentFunction'時(shí),外部變量a被賦值為“outer val”。函數(shù)返回一個(gè)指向內(nèi)部函數(shù)“childFunction”的指針,該指針包含在變量'val'中。

即使外部函數(shù)已經(jīng)返回,外部函數(shù)的局部變量 a 仍然存在。在 javascript 中,在調(diào)用 parentFunction 的那一刻,將創(chuàng)建一個(gè)具有屬性“a”的范圍對象。此屬性包含 arg1 的值,也稱為“outer val”。同樣當(dāng)parentFunction返回時(shí),它會(huì)返回內(nèi)部函數(shù)(childFunction),它包含在變量val中。

由于內(nèi)部函數(shù)持有對外部函數(shù)變量的引用,因此具有屬性“a”的作用域?qū)ο蟛粫?huì)被垃圾回收。

避免內(nèi)存泄漏

通過添加另一個(gè)函數(shù),將有兩個(gè)內(nèi)部函數(shù)。由于有兩個(gè)內(nèi)部函數(shù),因此沒有函數(shù)可以通過完全停止閉包來引用外部函數(shù)的變量。

當(dāng)沒有閉包時(shí),內(nèi)存泄漏的機(jī)會(huì)會(huì)減少。

<html>
<body>
<script>
   window.onload=function parentFunction(){
      var Obj1 = function childFunction1()
      {
         document.write("the leak is avoided");
      };
   (function childFunction2(){
      var obj2 = document.getElementById("closure");
      obj2.onclick=Obj1
      })(); //這個(gè)是立即執(zhí)行函數(shù)
   };
</script>
<input type = "button" id="closure" value ="Click Here">
</body>
</html>

demodownload

執(zhí)行代碼后,按鈕將顯示如下

 

按下按鈕后,我們將得到如下輸出:

the leak is avoided

總結(jié)

本文通過示例,介紹了閉包如何導(dǎo)致內(nèi)存泄漏以及如何防止它。閉包雖然功能強(qiáng)大,但它有一定的負(fù)面影響,所以在編程過程中,需要考慮是否真的需要用到閉包,而不用其他的處理方式。

什么是內(nèi)存泄漏?

內(nèi)存泄漏可以定義為一塊內(nèi)存不再被應(yīng)用程序使用或需要,但由于某種原因沒有返回給操作系統(tǒng)。簡單來說,它是永遠(yuǎn)等待使用的被遺忘的數(shù)據(jù)。泄漏是所有問題的根源:速度減慢、崩潰、高延遲,甚至是其他應(yīng)用程序的問題。

下面是內(nèi)存泄漏最簡單的例子。

let arr = []; 
for(let i = 5; i > 1; i++){ 
    arr.push(i-1)            // 警告!不要嘗試這個(gè)
}

該示例中,我們將運(yùn)行一個(gè)無限循環(huán),不斷地推入數(shù)組 i -1 直到填滿我們的內(nèi)存并且沒有任何東西可供我們使用。在這種情況下,垃圾收集并沒有真正起作用,因?yàn)槲覀冇羞@個(gè)數(shù)組并且我們一遍又一遍地使用這個(gè)數(shù)組,直到程序崩潰。

相關(guān)文章

標(biāo)簽: 閉包  內(nèi)存泄漏  
x
  • 站長推薦
/* 左側(cè)顯示文章內(nèi)容目錄 */