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

  找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是时时的,

  因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。

  什么叫不再使用的变量?不再使用的变量也就是生命周期结束的变量,当然只可能是局部变量

  全局变量的生命周期直至浏览器卸载页面才会结束。

  局部变量只在函数的执行过程中存在,而在这个过程中会为局部变量在栈或堆上分配相应的空间,

  以存储它们的值,然后再函数中使用这些变量,直至函数结束(闭包中由于内部函数的原因,外部函数并不能算是结束)

  

标记清除(mark and sweep)

这是JavaScript最常见的垃圾回收方式,

当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,

当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。

至于怎么标记有很多种方式,比如特殊位的反转、维护一个列表等,这些并不重要,重要的是使用什么策略,

大部分浏览器都是使用这种方式进行垃圾回收,区别在于如何标记及垃圾回收间隔而已,只有低版本IE,不出所料,又是IE。。。

引用计数(reference counting)

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

引用计数的策略是跟踪记录每个值被使用的次数,

当声明了一个变量B, 并将一个引用类型 A 赋值给该变量的时候, 这个值A的引用次数就加1,

如果该变量的值变成了另外一个,则这个值A的引用次数减1,

当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,

因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。

function test(){
var a = {} ; //a的引用次数为0
var b = a ; //a的引用次数加1,为1
var c =a; //a的引用次数再加1,为2
var b ={}; //a的引用次数减1,为1
}

看起来也不错的方式,为什么很少有浏览器采用,还会带来内存泄露问题呢?主要是因为这种方式没办法解决循环引用问题。

比如对象A有一个属性指向对象B,而对象B也有有一个属性指向对象A,这样相互引用

function test(){
var a={};
var b={};
a.prop=b;
b.prop=a;
}

这样a和b的引用次数都是2,即使在test()执行完成后,两个对象都已经离开环境,

在标记清除的策略下是没有问题的,离开环境的就被清除,但是在引用计数策略下不行,

因为这两个对象的引用次数仍然是2,不会变成0,所以其占用空间不会被清理,

如果这个函数被多次调用,这样就会不断地有空间不会被回收,造成内存泄露。

在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,

但BOM与DOM对象却是通过引用计数回收垃圾的,也就是说只要涉及BOM及DOM就会出现循环引用问题。

看上面的例子,有同学回觉得太弱了,谁会做这样无聊的事情,其实我们是不是就在做

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

这段代码看起来没什么问题,但是obj引用了document.getElementById("element"),

而document.getElementById("element")的onclick方法 innerFunction 会引用外部环境中的 活动变量 (arguments obj window等 ),

因为内部的函数会引用外部函数的整个作用域 来形成自己的作用域链

这个链自然也包括obj,是不是很隐蔽啊。

也就是obj的属性引用了obj本身

解决办法

最简单的方式就是自己手工解除循环引用,比如刚才的函数可以这样

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

什么时候触发垃圾回收

垃圾回收器周期性运行,如果分配的内存非常多,那么回收工作也会很艰巨,确定垃圾回收时间间隔就变成了一个值得思考的问题。

IE6的垃圾回收是根据内存分配量运行的,当环境中存在256个变量、4096个对象、64k的字符串任意一种情况的时候就会触发垃圾回收器工作,

看起来很科学,不用按一段时间就调用一次,有时候会没必要,这样按需调用不是很好吗?

但是如果环境中就是有这么多变量等一直存在,现在脚本如此复杂,很正常,那么结果就是垃圾回收器一直在工作,这样浏览器就没法儿玩儿了。

微软在IE7中做了调整,触发条件不再是固定的,而是动态修改的,初始值和IE6相同,

如果垃圾回收器回收的内存分配量低于程序占用内存的15%,说明大部分内存不可被回收,

设的垃圾回收触发条件过于敏感,这时候把临街条件翻倍,如果回收的内存高于85%,

说明大部分内存早就该清理了,这时候把触发条件置回。这样就使垃圾回收工作职能了很多。

同C# 、Java一样我们可以手工调用垃圾回收程序,但是由于其消耗大量资源,

而且我们手工调用的不会比浏览器判断的准确,所以不推荐手工调用垃圾回收。

 
 

http://www.jb51.net/article/75292.htm

http://www.cnblogs.com/dolphinX/p/3348468.html

js 的垃圾回收器 原理 坑 优化-- 待续的更多相关文章

  1. JVM垃圾回收器原理及使用介绍

    JVM垃圾回收器原理及使用介绍 垃圾收集基础 引用计数法(Reference Counting) 标记-清除算法(Mark-Sweep) 复制算法(Copying) 标记-压缩算法(Mark-Comp ...

  2. 关于 CMS 垃圾回收器,你真的懂了吗?

    大家好,我是树哥. 前段时间有个小伙伴去面试,被问到了 CMS 垃圾回收器的详细内容,没答出来.实际上,CMS 垃圾回收器是回收器历史上很重要的一个节点,其开启了 GC 回收器关注 GC 停顿时间的历 ...

  3. Java GC系列(3):垃圾回收器种类

    本文由 ImportNew - 好好先生 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 在这篇教程中我们将学习几种现有的垃圾回收器.在 ...

  4. [Java基础]-- Java GC 垃圾回收器的分类和优缺点

    https://blog.csdn.net/high2011/article/details/80177473?utm_source=blogxgwz2 参考:elasticsearch实战-使用G1 ...

  5. JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接

    原文 https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ 再插一个关于线程和进程上下文,待判断 http://b ...

  6. JVM 垃圾回收器工作原理及使用实例介绍

    IBM介绍文档:https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ Java 的新生代串行垃圾回收器中使用了复制 ...

  7. Java垃圾回收器的工作原理

    上课,老师照本宣科,实在难以理解,干脆就看书包里的Java书,正好看了Java的垃圾回收器是如何工作的,觉得有必要记录一下. 参考于 Java编程思想第四版(Thinking in Java) 老年代 ...

  8. 深入理解JAVA虚拟机原理之垃圾回收器机制(一)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随 ...

  9. 【转】V8 之旅: 垃圾回收器

    垃圾回收器是一把十足的双刃剑.其好处是可以大幅简化程序的内存管理代码,因为内存管理无需程序员来操作,由此也减少了(但没有根除)长时间运转的程序的内存泄漏.对于某些程序员来说,它甚至能够提升代码的性能. ...

随机推荐

  1. jquery 封装插件

    如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jq ...

  2. BZOJ 3992 【SDOI2015】 序列统计

    题目链接:序列统计 我来复习板子了……这道题也是我写的第一发求原根啊? 求原根方法: 从小到大依次枚举原根.设当前枚举的原根为\(x\),模数为\(p\),\(p-1\)的质因数分别为\(p_1,p_ ...

  3. poj 1523 SPF 无向图求割点

    SPF Description Consider the two networks shown below. Assuming that data moves around these network ...

  4. angular5 路由传参的几种方式

    此处介绍三种方式 方式一: 问号后面带的参数, 例如:/product?id=1&name=iphone还可以是: [routerLink]="['/books']" [q ...

  5. asp.net一般处理程序利用反射定位方法

    asp.net的一般处理程序我想大家用得都不少,经常会如下如下的代码: using System; using System.Collections.Generic; using System.Lin ...

  6. grub 启动错误 "file not found"

    刚安装ubuntu 14.4 竟然出现这么尴尬的事,ubuntu 行不行? 幸好还是能从u盘启动后,转到硬盘. 然后在网上找到了解决方法. http://askubuntu.com/questions ...

  7. Yii中的CComponent应用实例

    首先我们先了解一下如何创建一个CComponent,手册讲述如下: CComponent 是所有组件类的基类. CComponent 实现了定义.使用属性和事件的协议. 属性是通过getter方法或/ ...

  8. 通过IIS寄宿WCF服务

    WCF全面解析一书中的例子S104,直接将Service目录部署到iis是无法得到服务相应的,需要在项目中新建一个web项目,删除掉自动生成的所有文件之后,把Service目录下的Calculator ...

  9. Android发展历程

    Android历代版本的命名: 我们都是知道,安卓系统的历来的名称都是很有意思的,下面无限互联Android培训的老师归纳了一下:Android在正式发行之前,最开始拥有两个内部测试版本,并且以著名的 ...

  10. USACO 铂金 T1

    题意 给出一个数轴,每次可以选择停下并得到当前点的收益,或者继续随机向左右游走,走到边界游戏结束收益为0. 求从每个点出发的最大期望收益.(n<=1e5) 有一个显然的dp方程 这个方程是带环的 ...