什么是内存泄漏?
程序的运行需要内存,只要程序提出要求,操作系统或者运行就必须供给内存
对于持续运行的服务进程,必须及时释放内存,
不要再用到的内存,没有及时释放,就叫做内存泄漏
有些语言(比如C语言)必须手动释放内存,程序员复责内存管理,这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这就被称为垃圾回收机制。
js垃圾回收机制的原理
解决内存的泄漏,垃圾回收机制会定期(周期性)找出那些不在用到的内存(变量),然后释放其内存。
垃圾回收机制方法有2种:标记清除,引用计数
标记清除
当变量进入环境时,例如,在一个函数中声明一个变量,就将这个变量标记为"进入环境",从逻辑上讲,永远不能释放进入环境变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。而当变量离开环境时,则将其标记为"离开环境"
function test(){
var a=10; //被标记为"进入环境"
var b="hello"; // 被标记为进入环境
}
test(); // 执行完毕之后,a和b又被标记为"离开环境",被回收
垃圾回收机制在运行的时候回存储再内存中的所有变量都加上标记(可以是任何标记方式),然后,它会去掉处在环境中的变量及被环境中的变量引起的变量标记(闭包)。而在此之后剩下的带有标记的变量被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后垃圾回收机制到下一个周期运行时,将释放这些变量的内存,回收他们所占用的空间。
引用计数
语言引擎有一张"引用表",保存了内存里面所有资源(通常是各中值)的引用次数,如果一个值的引用次数是0,就表示这个值不在用到了,隐藏可以将这块内存释放。
上图中,左下角的两个值,没有任何引用,所以可以释放。
如果一个值不再需要了,引用数却不为0,垃圾回收机制无法释放这块内存,从而导致内存泄漏。
const arr = [1,2,3,4];
console.log("hello world");
上面的代码中,数组[1,2,3,4]是一个值,会占用内存。变量arr是仅有的对这个值的引用,因此引用次数为1.尽管后面的代码没有用到arr,它是会持续占用内存。
如果增加一行代码,解除arr对[1,2,3,4]引用,这块内存就可以被垃圾回收机制释放了。
let arr = [1,2,3,4];
console.log("hello world");
arr = null;
上面代码中,arr重置为null,就解除了对[1,2,3,4]的引用,引用次数变成了0,内存就可以释放出来了。