程序在运行的过程中会产生垃圾,这些垃圾积攒的太多了,就会导致程序运行的速度过慢,因此我们就需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾。
当一个对象没有任何的变量或是属性对它进行引用,此时我们就永远无法操作该对象,该对象就是一个垃圾,这种对象过多的话就会占用大量的内存空间,导致运行程序变慢,这种垃圾就必须进行清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作,我们仅需将我们不再使用的对象设置为null即可。
对于局部变量来说,它只在函数执行的过程中存在,在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间来存储他们的值,在函数执行过程中我们可以使用这个值,函数执行结束后,这个局部变量就没有存在的意义了,因此可以释放它们的内存以供将来使用,这种情况可以很容易判断变量是否有存在的意义,而有一些情况我们没有那么容易判断。垃圾回收收集器就需要跟踪变量,将不再有用的变量作一个标记。具体到浏览器中的实现通常情况下有两种策略。
1、标记清除是js中最常用的垃圾收集方式。 2、原理:变量进入环境,如在函数中声明一个变量,就将这个变量标记为“进入环境”,离开环境时,则标记为“离开环境”,如该变量所在函数执行结束。
3、标记变量不重要,关键在于采取什么策略。 4、垃圾收集器在运行时,会给存储在内存中的所有变量都加上标记,接着,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而此后再被加上标记的变量将被视为准备删除的变量,因为环境中的变量已经无法访问这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。各浏览器,如Firefox、Chrome等的JavaScript实现都是使用的标记清除式的垃圾收集策略(或类似的),只不过垃圾收集时间间隔有所不同。
引用计数垃圾收集策略不太常见。
1、含义:跟踪记录每个值被引用计数的次数。当声明了一个变量并将一个引用类型值赋给该变量时,这个值的引用次数就是1.如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,该值的引用次数减1。当引用次数为0时,则将其所占用的内存空间回收。 2、存在的问题
循环引用 对象A中包含一个指向对象B的指针,对象B中也包含一个指向对象A的指针。 如:function problem(){ var objectA = new Object(); var objectB = new Object(); objectA.otherObject = objectB; objectB.anotherObject = objectA; } 函数执行完毕,objectA和objectB仍然存在,引用次数永远不会为0。若这个函数被重复多次调用,将导致大量的内存空间得不到回收。 COM IE其BOM和DOM中的对象以COM(组件对象模型)对象的形式实现的。COM对象的垃圾回收收集机制采用的是引用计数策略。 如: var element = document.getElementById("some_element"); var myObject = new Object(); myObject.element = element; element.someObject = myObject; 解决:myObject.element = null; element.someObject = null; 手工断开原生JavaScript对象与DOM元素之间的链接,消除创建的循环引用。一旦数据不再有用,将其值设置为null来释放其引用,这一做法适用于大多数全局变量和全局对象的属性。 注意:解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。
