|
|
|
|
|
|
閉包一個強大優勢是內部函數可以訪問外部函數的變量,但是也正是這一個特征,讓閉包容易產生內存泄露的負面影響。
Javascript 允許嵌套函數(函數中的函數)訪問父函數的變量,內部函數訪問外部函數變量的過程稱為閉包。
但是一旦一個變量被任何閉包使用,它就會在該范圍內所有閉包共享的詞法環境中結束,這可能導致內存泄漏。

示例
<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>
執行結果

在該示例中,“childFunction”是在“parentFunction”外部函數中定義的內部函數。當使用參數“outer val”調用'parentFunction'時,外部變量a被賦值為“outer val”。函數返回一個指向內部函數“childFunction”的指針,該指針包含在變量'val'中。
即使外部函數已經返回,外部函數的局部變量 a 仍然存在。在 javascript 中,在調用 parentFunction 的那一刻,將創建一個具有屬性“a”的范圍對象。此屬性包含 arg1 的值,也稱為“outer val”。同樣當parentFunction返回時,它會返回內部函數(childFunction),它包含在變量val中。
由于內部函數持有對外部函數變量的引用,因此具有屬性“a”的作用域對象不會被垃圾回收。
避免內存泄漏
通過添加另一個函數,將有兩個內部函數。由于有兩個內部函數,因此沒有函數可以通過完全停止閉包來引用外部函數的變量。
當沒有閉包時,內存泄漏的機會會減少。
<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
})(); //這個是立即執行函數
};
</script>
<input type = "button" id="closure" value ="Click Here">
</body>
</html>
執行代碼后,按鈕將顯示如下

按下按鈕后,我們將得到如下輸出:
the leak is avoided
總結
本文通過示例,介紹了閉包如何導致內存泄漏以及如何防止它。閉包雖然功能強大,但它有一定的負面影響,所以在編程過程中,需要考慮是否真的需要用到閉包,而不用其他的處理方式。
什么是內存泄漏?
內存泄漏可以定義為一塊內存不再被應用程序使用或需要,但由于某種原因沒有返回給操作系統。簡單來說,它是永遠等待使用的被遺忘的數據。泄漏是所有問題的根源:速度減慢、崩潰、高延遲,甚至是其他應用程序的問題。
下面是內存泄漏最簡單的例子。
let arr = [];
for(let i = 5; i > 1; i++){
arr.push(i-1) // 警告!不要嘗試這個
}
該示例中,我們將運行一個無限循環,不斷地推入數組 i -1 直到填滿我們的內存并且沒有任何東西可供我們使用。在這種情況下,垃圾收集并沒有真正起作用,因為我們有這個數組并且我們一遍又一遍地使用這個數組,直到程序崩潰。
相關文章
