垃圾是如何产生的
垃圾回收的目的就像我们给手机清除没有作用的缓存,这些缓存占用了内存的空间,降低了浏览器的运行效率,所以要利用垃圾缓存机制,清除在浏览器没用被使用的数据,释放内存。
创建一个基本类型、对象、函数等,都是需要占用内存的,JavaScript基本数据类型存储在栈内存中,引用数据类型存储在堆内存中,但是引用数据类型会在栈内存中存储一个实际对象的引用。
堆内存回给一个对象开辟了一个空间来存放,栈内存中存放了该引用的地址,如果我们将这个对象重新赋值为一个数组,也就是说引用地址从原来的对象变成了数组,原来的引用关系就没有了,那么这时原来的对象在堆内存中就会成为一个垃圾。
var son={
name:'张三'
}
son = [ 1,2,3]
console.log(son);
解决垃圾的办法
JavaScript中主要的内存管理概念是可达性。内存的数据一直被获取
1.标记清除法
2.引用计数法
1.标记清除法
优点:标记清除法的优点就是实现简单。
缺点:①内存碎片化。这是因为清理掉垃圾之后,未被清除的对象内存位置是不变的,而被清除掉的内存穿插在未被清除的对象中,导致了内存碎片化。②内存分配速度慢。由于空闲内存不是一整块,假设新对象需要的内存是size
,那么需要对空闲内存进行一次单向遍历,找出大于等于size
的内存才能为其分配。
因为标记标记清除法这些缺点又有一种方法针对他第一种缺点改进了一下——标记清除法
优点:标记整理算法的标记阶段与标记清除算法相同,都是从根节点遍历内存中的所有对象,为可达的对象打上一个标记。但是在标记结束后,标记整理算法将这些可达的对象移向内存的一端,然后清理掉边界的内存。
2.引用技术法
优点:可以实现立即进行垃圾回收,当引用计数在引用值为0时,立即进行垃圾回收。
缺点:①它需要一个计数器,这个计数器可能要占据很大的位置,因为我们无法知道被引用数量的多少。②无法解决当出现循环引用时无法回收的问题。例如a
引用了b
,b
也引用了a
,两个对象相互引用,引用计数不为0,因此无法进行内存清理,如下所示:
var a = { name: "橘猫吃不胖" };
var b = { age: 2 };
a.age = b;
b.name = a;