javascript 中的垃圾回收机制
[JavaScript] 纯文本查看 复制代码 function sf() {
var num = 0
return function inner() {
console.log(num)
}
inner()
}
var fn = sf()
fn()
fn()
fn()
把一个内部的函数,通过return的形式,拿到了全局范围,然后就变成了全局函数。本来num是一个局部变量,本来它被用完了应该被清理,但是现在不清理,这个num变量会一直存在,一直到全部的调用都消失了,才会清理。
垃圾回收机制的常见算法
引用计数法(浏览器):
用的较多
计数法的意思就是给每个变量贴标签,只要有一个人用我就给他写个数字:1,两个人用我就写:2,三个人用就是:3;其中有一个人不用了我可以把技术撤掉,把3改回2。总之就是上面有个数字,代表几个人在使用。
这对于GC来说就简单了,它巡视查看内存的时候只要看这个变量的计数是不是等于0,如果等于0毫不犹豫的清理掉,不等于0说明还有人在使用就不能清理。
这种方式容易产生很多碎片,有些空间能用有些被占用了,不会连续,我们说硬盘里时不时要做碎片整理,就是为了让我们硬盘空间利用效率更高,所以说最好就是时不时的把空间规整一下,排个序。
复制整理法(Java内存管理):
不停在用,整个过程都不清理。一口气把所有的已经占用对的空间复制一遍,它在整个复制的过程中把所有的内存扫描了一遍,复制的时候把没用的清理了,而且做了重新排序。
缺点:你的内存必须得一分为二,可能有一半空间不能利用。如果你内存大不在乎,这种方式是不错的选择
标记清除法(浏览器):
用的不多
不停的增加,每隔一段时间就使劲的扫描内存,并且清理,过一段时间再扫描,和引用计数法一样,同样会存在碎片
标记整理法(浏览器):
用的较多
当变量越来越多的时候,它也会定期的进行扫描,扫描完了它从头到尾做了一个排序,一边清除,一边排序,工作量蛮大的
闭包中的变量num为什么不会被回收?
明白了垃圾回收机制,那么闭包中的num为什么不会被回收,应该就可以解释了吧!外面的全局函数还在使用num,因此num身上有计数,不为零,所以它不会被清除。
内存泄漏常见情况
闭包写多了就会造成内存泄漏,一般不可能代码里全是闭包,我们只能说有这个风险
大量的使用全局变量,现在基本不会出现,因为我们现在都模块化了,全局变量很少用
定时器,这个可能性大一些,我们总是开启了就忘记了关闭,经常犯
DOM元素的引用:
[JavaScript] 纯文本查看 复制代码 <body>
<button id = 'btn'>按钮</button>
</body>
<script>
var btn = document.getElementById('btn')
btn.remove() // 这个按钮就不会出现在页面上了
// 但是在控制台(console.log())输入btn ,结果就是还有
// 为什么还有?
// 页面是不存在了,但是页面上还有
// 就是因为全局变量 btn ,btn.remove删除了节点,但是它就还被保留在内存当中
</script>
解决方案
[JavaScript] 纯文本查看 复制代码 btn = null // 现在被释放了
|