闭包,内存泄漏

闭包定义

有权访问另一个函数作用域中变量的函数

  • 闭包函数
function fa() {
    var a = 1;
    return function () {
        console.log(a)
        a++
    }
}
var o = fa();
o(); // 1
o(); // 2

闭包内存泄漏

  • 什么叫内存泄漏
程序运行就需要内存
持续运行的服务进程,必须及时释放不再用到的内存,
不然内存越战越高,轻则影响系统性能,重则导致程序崩溃

  • 内存泄漏情况
1 意外的全局变量
2 闭包引起(为了维护函数内部的局部变量,使其不得释放)
3 未被清理的DOM
4 被遗忘的定时器,或者回调  // ?


  • 内存泄漏案例
function leaks(){  
    leak = 'xxxxxx'; // leak 成为一个全局变量,不会被回收
}

function fa() {  // 闭包
    var a = 1;
    return function () {
        console.log(a)
        a++
    }
}
var obj1 = {};
var obj2 = [};
obj1.a = obj2;
obj2.b = obj1;      // 相互引用,即使不在使用也清除不掉



btn.click = () => {
var div = document.getElementById('box');
div.onclick = function(){
		.....
}; 


  • 垃圾回收机制V8
1 标记清除
2 引用计数

js新生成一个对象(比如函数),就会在堆内存中消耗一块内存。代码中可能有很多个变量会指向这个对象,js会跟踪这些指针,当最后一个指针不再指向这个对象时,那么这个对象占用的内存就会被释放

闭包如何导致内存泄漏的?

  • 先了解,执行环境
执行环境:
定义了变量和函数的有权访问权限,环境中定义的变量和函数都保存在这个对象中(函数是对象
放在堆内存中),函数执行完毕,环境被销毁,变量和函数定义也被销毁

全局环境,程序退出才会被销毁
  • 作用域链
代码在执行环境中,他能够访问到的变量和函数,以及其访问顺序(先局部,然后再全局)

  • 看案例代码
  function test() {
        var str = "hello";
        return function () {
            console.log(str)
        }
    }
    var o = fa();
    o();
var str
hello
var obj
function
  • 代码分析
在堆上有两个对象
对象1: ‘hello'
对象2: function(){console.log(a)}

var str =  'hello' // 对象1被引用一次,计数1
function(){console.log()} // 这里再次引用对象1,计数 1+1 = 2

fa()执行完毕  :
// 保存在其中的变量var str 被销毁,所以这个时候,对象1的引用次数2-1=1

o()执行完毕后,对象1的引用次数还是1,所以他不会被GC回收

而且:这里o对对象2引用了一次,执行完o()后,并没有o=null,清除对对象2的引用

猜你喜欢

转载自blog.csdn.net/qq1498982270/article/details/88786874