[实例]分析JS闭包如何导致内存泄漏以及如何防止它
作者:admin 时间:2022-6-3 14:48:32 浏览:闭包一个强大优势是内部函数可以访问外部函数的变量,但是也正是这一个特征,让闭包容易产生内存泄露的负面影响。
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 直到填满我们的内存并且没有任何东西可供我们使用。在这种情况下,垃圾收集并没有真正起作用,因为我们有这个数组并且我们一遍又一遍地使用这个数组,直到程序崩溃。
相关文章
- 站长推荐