如果变量长生不老,那么聊聊内存溢出

422 阅读3分钟

页面突然卡的要死,前端媛眼眶子都红了,于是程序猿们纷纷上前,抓耳挠腮,指点江山,但是,问题还是没有解决,媛妹子的眼眶中已经蓄满了眼泪,马上就要哭出声来,这时路过的外卖哥哥扫了一眼:”this变量导致的。“然后,嗯,我们聊聊前端的内存泄漏吧。

内存泄漏

众所周知,计算机运行程序的时候,需要把程序相关的代码,数据加载到内存当中去运算,但是内存大小是有限的,加入一直使用,不释放内存,占用内存越来越多,那么就会越来越卡,这种情况下,占用内存不释放,就是内存泄漏,当然如果可以分配的内存不足,也就形成了内存溢出,这些情况轻者卡顿,重者崩溃,所以还是需要注意的。

JS内存泄漏

js有自己的垃圾回收机制,这个之前我们聊过,但是,如果开发者的编程习惯不好的话,还是很容易导致内存泄漏的,接下来我们来盘点一下JS常见的内存泄漏的原因。

1、全局变量

这个是好多新手程序猿容易犯的错误,在初学前端的时候,对window对象并不了解,一定要注意,window对象的属性只有在关闭页面或者浏览器的时候才会触发垃圾回收机制。

这种类型的声明很少,但却是见过。

window.username = "laobian"

跟多的原因是由于对this变量不熟悉,忽略函数当中this指向导致的,就是开头妹子犯的错误。

<script>
    function example(){
        this.name = "laobian"
    }
    example() //由于全局调用example,所以,example当中的this指向的是window
</script>

当然解决方法也很简单,调用完成,将变量的值变成null

image.png

2、闭包

这个在我们之前聊闭包的时候是聊过的,闭包会形成局部的作用域,在嵌套函数当中调用过的变量是不会被垃圾回收的,所以需要手动的去删除,闭包嵌套函数调用的变量。

<script>
    function outer(){
        obj = {name: "laobian"};
        function inner(){
            obj.name = 1; //内部函数的调用导致our结束之后,obj并没有被释放
        };
        obj = null; //手动删除
    }
</script>

3、定时器

这个就见的就很多了,就是如果销毁一个dom元素,但是这个dom元素在定时器当中有被调用,那么,按照垃圾回收机制,这个对象在定时器当中一直有引用,所以内存依然不会释放。

<script>
    var name = "laobian";
    consot timer = setInterval(function(){
        var obj = document.getElementById("obj_id");
        obj.innerHTML = name;
    })
</script>

这种情况下,如果像删除obj元素或者name对象的话,单纯的销毁她两是不够的,还需要把计时器设置为null,也就是:

timer = null;

4、JS当中的DOM监听事件

这个也和第一点类似,也是由于全局(window)监听事件导致的,当然还是需要手动的删除。

<script>
    function clickFun(){
        console.log("do some things after click")
    }
    
    var obj = document.getElementById("obj_id");
    obj.addEventListener('click', clickFun) //这里如果想要删除clickFun或者obj就需要先移除这个监听器
    //移除方法
    obj.removeEventListener('click', clickFun)
</script>

总结

当然还有很多,比如vue当中的v-if嵌套元素导致的内存溢出,等等,总之,当你跨过编程的新手期,可以独立完成一个功能的时候,请注意每个变量,每个元素的声明周期,假如他长生不老,那么你就要注意了。最后还是请各位大佬多多指点