标签:相互 循环引用 碎片 执行 变量 font 回收 就是 环境
js中所谓垃圾,一般来说指的是无法被访问到的内存,不同于偏向底层的C,js会有一套固定的算法,定期地清除这些垃圾,防止出现内存泄漏,本篇文章首先会介绍什么样的内存区域会被定义为垃圾,接下来会介绍几个常见的垃圾回收算法。
何为垃圾
1.没有被任何内容引用的对象
我们来看下面这段代码
var x={name="first"}; x={name="second"};
首先变量x指向了一个名为first的对象(这里不严谨地将对象的name属性作为该对象的代号),接下来它改变指向,指向了一个新的,名为second的对象,之前的first对象无法被访问到,系统会将其判定为垃圾。
2.互相引用,但他们作为一个整体无法被外界引用到的对象
这种情况也是导致引用计数算法出错的根源,看如下代码:
function comb(x,y){ x.friend=y; y.friend=x; return {left:x,right:y}; } var x={name:"a"}; var y={name:"b"}; var father=comb(x,y);
该代码用变量father指向两个对象x和y,而通过函数comb,将x和y相互绑定
此时,如果执行如下操作:
father.left=null; father.right=null;
则尽管x和y都有被引用,但是x和y的整体无法被访问到,一样会被视为垃圾。
3.对于基本数据类型变量
这个相对引用类型会更好理解,即刚进入环境的变量不会被视为垃圾,但是退出环境的变量即视为垃圾,也就是说,一个局部变量一旦脱离了创建他的环境(可以出现在该环境内的子环境中),就会被视为垃圾,进行回收。典型的例子就是函数中定义的局部变量,当函数执行完毕后,这些变量就会被释放。
由于在栈中,函数结束后本身就会释放堆栈内存,所以这种垃圾并不在我们经常讨论的范围内,一般垃圾回收的对象都是堆中的对象。
GC算法
一.标记-清除算法
算法步骤:
1.标记内存中的所有内容
2.将根及其所有可访问到的后代清除标记
3.删除所有含标记的内容
缺点:
会产生大量碎片,影响内存的使用效率
二.标记-压缩算法
与标记-清除算法的不同之处在于会将非垃圾在堆中集中靠前,这样的操作避免的大量碎片的产生,但是在时间效率上过低,因为要在堆中移动对象。
三.引用计数法
作为最原始的垃圾回收算法,其主要步骤如下:
1.每个对象都维护一个引用计数值,用于表示当前该对象被多少变量引用了
2.该对象每次赋值给一个新变量,计数值+1
3.每次引用该对象的变量有了新的对象,引用值-1
4.如果某时该对象计数值为0,视为垃圾,清除之
缺点:无法处理上述循环引用的问题
该方法由于缺陷,在较新版本的浏览器中已不使用。
标签:相互 循环引用 碎片 执行 变量 font 回收 就是 环境
原文地址:https://www.cnblogs.com/hygcoding/p/12972865.html