JavaScript垃圾回收vnsc5858威尼斯城官网:

时间:2019-05-11 09:48来源:计算机教程
JavaScript具有强大的垃圾回收功能,执行环境负责管理代码执行过程中使用的内存。其基本原理是:在执行环境中找出那些不再继续使用的变量,然后释放其占用的内存。垃圾收集器会按

  JavaScript具有强大的垃圾回收功能,执行环境负责管理代码执行过程中使用的内存。其基本原理是:在执行环境中找出那些不再继续使用的变量,然后释放其占用的内存。垃圾收集器会按照系统编写号的时间间隔,周期性地执行操作。

  JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。而在C和C 之类的语言中,开发人员的一项基本任务就是手工跟踪内存的使用情况,这是造成许多问题的一个根源。在编写JavaScript程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存。为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作。

 

  下面我们来分析一下函数中局部变量的正常生命周期。局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值。然后在函数中使用这些变量,直至函数执行结束。此时,局部变量就没有存在的必要了,因此可以释放它们的内存以供将来使用。在这种情况下,很容易判断变量是否还有存在的必要;但并非所有情况下都这么容易就能得出结论。垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存。用于标识无用变量的策略可能会因实现而异,但具体到浏览器中的实现,则通常有两个策略。

局部变量的生命周期

标记清除##

  JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。

  可以使用任何方式来标记变量。比如,可以通过翻转某个特殊的位来记录一个变量何时进入环境,或者使用一个“进入环境的”变量列表及一个“离开环境的”变量列表来跟踪哪个变量发生了变化。说到底,如何标记变量其实并不重要,关键在于采取什么策略。

  垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

  到2008年为止,IE、Firefox、Opera、Chrome和Safari的JavaScript实现使用的都是标记清除式的垃圾收集策略(或类似的策略),只不过垃圾收集的时间间隔互有不同。

  一个函数中局部变量正常生命周期,局部变量只在函数执行的过程中存在,而在执行的过程中,会为,局部变量在栈或者堆内存上分配内存空间,以便存储他们的值。然后再函数中使用这些变量,直至函数执行结束。在这个时候,局部变量就没有存在的必要了,因此可以释放它们的内存供将来变量使用。

引用计数##

  另一种不太常见的垃圾收集策略叫做引用计数(reference counting)。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。

  Netscape Navigator 3.0是最早使用引用计数策略的浏览器,但很快它就遇到了一个严重的问题:循环引用。循环引用指的是对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。请看下面这个例子:

function problem(){
    var objectA = new Object();
    var objectB = new Object();
    objectA.someOtherObject = objectB; 
    objectB.anotherObject = objectA;
}

  在这个例子中,objectA 和 objectB 通过各自的属性相互引用;也就是说,这两个对象的引用次 数都是 2。在采用标记清除策略的实现中,由于函数执行之后,这两个对象都离开了作用域,因此这种 相互引用不是个问题。但在采用引用计数策略的实现中,当函数执行完毕后,objectA 和 objectB 还 将继续存在,因为它们的引用次数永远不会是 0。假如这个函数被重复多次调用,就会导致大量内存得 不到回收。为此,Netscape 在 Navigator 4.0 中放弃了引用计数方式,转而采用标记清除来实现其垃圾收 集机制。可是,引用计数导致的麻烦并未就此终结。
  我们知道,IE 中有一部分对象并不是原生 JavaScript 对象。例如,其 BOM 和 DOM 中的对象就是使用 C 以COM(Component Object Model,组件对象模型)对象的形式实现的,而 COM 对象的垃圾 收集机制采用的就是引用计数策略。因此,即使 IE 的 JavaScript 引擎是使用标记清除策略来实现的,但 JavaScript 访问的 COM 对象依然是基于引用计数策略的。换句话说,只要在 IE 中涉及 COM 对象,就会 存在循环引用的问题。下面这个简单的例子,展示了使用 COM 对象导致的循环引用问题:

var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.someObject = myObject;

  这个例子在一个 DOM 元素(element)与一个原生 JavaScript 对象(myObject)之间创建了循环 引用。其中,变量 myObject 有一个名为 element 的属性指向 element 对象;而变量 element 也有 一个属性名叫 someObject 回指 myObject。由于存在这个循环引用,即使将例子中的 DOM 从页面中 移除,它也永远不会被回收。
  为了避免类似这样的循环引用问题,最好是在不使用它们的时候手工断开原生 JavaScript 对象与 DOM 元素之间的连接。例如,可以使用下面的代码消除前面例子创建的循环引用:

myObject.element = null;
element.someObject = null;

  将变量设置为 null 意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就 会删除这些值并回收它们占用的内存。
  为了解决上述问题,IE9 把 BOM 和 DOM 对象都转换成了真正的 JavaScript 对象。这样,就避免了 两种垃圾收集算法并存导致的问题,也消除了常见的内存泄漏现象。

<<JavaScript高级程序设计>>

function car() {
    var wheel = 100;
    return console.log(wheel);//100
}
car();
console.log(wheel);//不能够访问,输出错误

vnsc5858威尼斯城官网 1

垃圾收集器想要收集废掉的变量,可以在其废掉的变量打上标记,用于收回占用的内存,标识废掉的变量策咯会因实现而不同,在浏览器中实现,通常有两种策咯。

  标记清除

  这个JavaScript中最常用的垃圾收集方式,每当一个变量进入环境,就将这个变量标记为“进入环境“。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就会使用到,而当变量离开环境时,则标记为”离开环境“。

vnsc5858威尼斯城官网 2

  引用计数

  引用计数一般的原理是:声明一个变量,则该值的引用次数加1,如果同一个值又被赋给另一个变量,则该值的引用次数加1,相反,如果包含对这个值引用的变量又取得了另外一个值,那么这个值引用次数减1,当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间收回来。

vnsc5858威尼斯城官网,问题:循环引用

循环引用指的是,A对象中包含一个指向B对象的指针,而对象B中也包含一个指向对象A的引用。

function problem() {
    var objectA = new Object();
    var objectB = new Object();

    objectA.prototype1 = objectB;
    objectB.prototype2 = objectA;
}

编辑:计算机教程 本文来源:JavaScript垃圾回收vnsc5858威尼斯城官网:

关键词:

  • 上一篇:没有了
  • 下一篇:没有了