美文网首页
JavaScript的垃圾回收

JavaScript的垃圾回收

作者: HelloJames | 来源:发表于2018-01-06 20:47 被阅读13次

JavaScript的垃圾回收

前段时间读了一下<<JavaScript高级程序设计>>(书名很吓人, 实际上作者写得很好, 由浅入深), 了解了一下JavaScript的垃圾回收机制.

和Java一样, JavaScript有自动垃圾回收机制.

JavaScript的垃圾回收机制很简单:

找出不再使用的变量, 然后释放掉其占用的内存, 但是这个过程不是实时的, 因为开销太大, 所以垃圾回收器会按照固定的时间周期性执行.

变量生命周期

变量主要分为: 全局变量和局部变量.
全局变量的生命周期直至浏览器关闭页面才会结束, 而局部变量只在函数执行的过程中存在, 而在这个过程中会为局部变量在栈或堆上分配相应的内存空间, 以存储它的值, 然后再在函数中使用这些变量, 直至函数结束(闭包中由于内部函数的原因, 外部函数并不能算是结束了, 了解闭包可以看看JavaScript作用域链和闭包究竟是什么?)

一旦函数结束, 局部变量就没有存在的必要了, 可以释放它们占用的内存.看似好像很简单的工作, 为什么会有很大的开销呢? 垃圾回收器需知道哪些变量有用, 哪些变量没用, 对于不再有用的变量打上标记, 以备将来回收. 用于标记无用的策略很多, 常见的有两种: 标记清除和引用计数.

标记清除

这是JavaScript常见的垃圾回收方式, 当变量进入执行环境时, 比如函数中声明一个变量, 垃圾回收器将其标记为"进入环境", 当变量离开环境的时候(函数执行结束), 将其标记为"离开环境". 至于怎么标记有很多方法. 比如特殊位的反转, 维护一个列表等.

垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记, 然后去掉环境中的变量以及被环境变量所引用的变量(闭包), 在这些完成之后仍存在标记的就是要删除的变量, 因为环境中的变量已经无法访问到这些变量了, 然后垃圾回收器会清除这些标记的变量所占的内存空间.

大部份的浏览都是使用这种方式进行垃圾回收, 区别在于如何标记及垃圾回收间隔罢了.只有低版本的IE...

引用计数

在低版本的IE中经常会出现内存泄露, 很多时候是因为其采用引用计数方式进行垃圾回收.

引用计数的策略是:

跟踪记录每个值被使用的次数, 当声明一个变量并将一个引用类型赋值给该变量的时候, 这个值的引用次数
就加1, 如果该变量的值变成另一个, 则这个值的引用次数减1, 当这个值的引用次数为1时, 说明没有变量在使用, 这个值没法被访问了. 因此可以将其占用的内存空间回收. 这样垃圾回收器会在运行的时候清理掉引用次数为0的变量所占的内存空间.

看起来不错的方式, 为什么很少有浏览器采用, 还会带来内存泄露呢?
主要是因为这种方式没法解决循环引用问题. 比如对象A有一个属性指向对象B, 而对象B也有一个属性指向对象A, 这样的相互引用.

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收, 但BOM与DOM对象却是通过引用计数回收垃圾的,也就是说只要涉及BOM及DOM就很可能会出现循环引用的问题.如:

window.onload = function outFunction(){
    var obj = document.getElementById("element");
    obj.onclick = function innerFunction(){};
}

这段代码看起来没什么问题, 但是obj引用了document.getElementById("element"), 而document.getElementById("element")的onclick方法会引用外部环境中的变量, 自然也包括obj, 是不是很隐蔽?

解决办法:
最简单的办法就是自己手工解除循环引用, 比如上面的例子:

window.onload = function outFunction(){
    var obj = document.getElementById("element");
    obj.onclick = function innerFunction(){};
    obj = null;
}

什么时候触发垃圾回收

垃圾回收器周期运行, 如果分配的内存非常多, 那么回收工作会很困难, 确定垃圾回收时间间隔变成了一个值得思考的问题. IE6的垃圾回收是根据内存分配量运行的, 当环境中存在256个变量, 4096个对象, 64K的字符串任意一种的情况下, 就会触发垃圾回收器工作, 看起来很科学, 不用按一段时间就调用一次, 但有时候会没有必要, 这样按需调用不是很好吗? 但如果环境中就是有这么多变量一直存在, 现在脚本如此复杂, 很正常, 那么结果就是垃圾回收器一直在工作, 这样浏览器就没法玩了.

微软在IE7中做了调整, 触发条件不再是固定的, 而是动态修改的, 初始值和IE6相同, 如果垃圾回收器回收的内存分配量低于程序占用内存的15%, 说明大部分内存不可被回收, 设的垃圾回收触发条件过于敏感, 这时就把临界条件*2, 如果回收的内存高于85%, 说明大部分内存该清理了, 这时把触发条件重置, 这样就使得垃圾回收工作变得智能很多.

同Java一样, 我们可以手工调用垃圾回收程序, 但由于其消耗大量资源, 而且手工调用的不会比浏览器判断的准确, 所以不推荐手工调用垃圾回收.

相关文章

  • 垃圾回收机制

    垃圾回收机制—GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就...

  • JavaScript中的垃圾回收

    垃圾回收概述 JavaScript具有垃圾自动回收机制 原理是:找出不再使用的变量,释放其内存空间,为此垃圾回收器...

  • JS 的垃圾回收机制与内存管理

    垃圾回收机制 Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,...

  • JavaScript垃圾回收机制

    什么是垃圾回收机制? 和java,c#一样,javascript也有垃圾回收的机制,比如说c++和c就没有垃圾回收...

  • JavaScript垃圾回收机制

    JavaScript具有自动垃圾回收机制,回收原理很简单:找到那些不再使用的变量,然后释放其内存空间,垃圾回收器会...

  • JavaScript中的垃圾收集

    JavaScript具有自动垃圾回收机制,垃圾回收机制会按照固定的时间间隔周期性地执行这一操作,垃圾回收机制必须跟...

  • JavaScript垃圾回收

      JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。而在C和C++...

  • JavaScript垃圾回收

    垃圾回收机制 1. 标记清除 当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。内存...

  • JavaScript的垃圾回收机制

    JavaScript采用的垃圾回收机制是标记扫描算法(Mark-and-sweep algorithm),它会回收...

  • JavaScript的垃圾回收

    JavaScript的垃圾回收 前段时间读了一下<>(书名很吓人, 实际上作者...

网友评论

      本文标题:JavaScript的垃圾回收

      本文链接:https://www.haomeiwen.com/subject/tphunxtx.html