原文:从头开始学JavaScript (十)——垃圾收集

一、垃圾收集

1.1javascript垃圾收集机制:

自动垃圾收集,执行环境会负责管理代码执行过程中的使用的内存。而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况,这是造成许多问题的一个根源。在编写javascript程序时候,开发人员不用再关心内存使用的问题,所需内存的分配 以及无用的回收完全实现了自动管理。

1.2垃圾收集原理:

  • 找出那些不再继续使用的变量,然后释放其中占用的内存。
  • 垃圾收集器会按照固定的时间间隔(或代码执行中预设的收集时间),周期性的执行这一操作。

1.3垃圾收集方法:

1.3.1标记清除:当变量进入环境时标记“进入环境”,而当变量离开环境时,这将其 标记为“离开环境”。

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

例如:

         function countMethod(){
var object1 = new Object(); // 声明变量,计数器由 0 变为 1
var object2 = new Object(); // 声明变量,计数器由 0 变为 1
object1.method1 = "This is object1"; // object1 计数器 -1,object1 读数变为0
object2.method2 = "This is object2"; // object2 计数器 -1,object2 读数变为0
}

当函数运行结束后,object1 object2的读数均为 0,在下一个垃圾收集周期时,会被回收并且释放其所占用的内存。

可以把引用计数想象成猴子掰玉米,玉米的使用权是变量(之所以是使用权而不是玉米本身,是因为引用计数是对引用类型值而言的),猴子是计数器。第一个猴子拿到玉米使用权,计数器+1;第二个猴子来和第一个猴子分享玉米的使用权,计数器+2;其中一个猴子发现一个更大的玉米的使用权,放弃这个玉米的使用权,计数器—1,另一个猴子也发现一个更大的玉米的使用权,放弃这个玉米的使用权,计数器就变成0,这个玉米就被回收了~(例子举得不恰当还望见谅,只是帮助理解~)

再看下面一个例子:

             function countMethod(){
var object1 = new Object(); // 声明变量,计数器由 0 变为 1
var object2 = new Object(); // 声明变量,计数器由 0 变为 1
object1.method1 = object2; // object1 计数器 -1,object2 计数器 +1
object2.method2 = object1; // object1 计数器 +1,object2 计数器 -1
}

这个例子就相当于两个猴子都分别有一个玉米使用权,但是总觉得对方手里的玉米的使用权所对应的玉米比自己大,所以不停地在交换玉米的使用权。也就是循环引用。(例子举得不恰当还望见谅,只是帮助理解~)

此函数运行退出后,object1 的计数器读数为 1,object2 的计数器度数为 1。所以两个变量都不会被销毁。如果大量的这样的程序存在于函数体内,就会导致大量的内存被浪费而无法回收,从而导致内存的泄露。

上述问题可以通过手动释放 object1 object2 所占用的内存来消除。即

                  object1.method1 = null;
object2.method2 = null;

二、性能问题

垃圾收集器都是周期性运行的,而且如果为变量分配的内存数量很客观,那么回收工作量也是相当大的。在这种情况下,确定垃圾收集的时间间隔是一个非常重要的问题。说到垃圾收集器多长时间运行一次,不禁让人联想到IE因此声名狼藉的性能问题。IE的垃圾收集器是根据内存分配量运行的,具体一点说就是256个变量、4096个对象(或数组)字面量和数组元素(slot)或者64KB的字符串。达到上述任何一个临界值,垃圾收集器就会运行。这种实现的问题在于,如果一个脚本中包含那么多变量,那么该脚本很可能会在其生命周期中一直保持那么多的变量。而这样一来,垃圾收集器就可能不得不频繁的运行。结果,由此引发的严重性能问题初始IE7重写了其垃圾收集例程。

【上面这段话可以这么理解:垃圾收集器可以看做是勤劳的环卫工人,内存分配量可以看做是垃圾箱的容积,如果一个小区的居民造垃圾的能力是单位时间恒定的,也就是说每个回收周期都能把垃圾箱堆满,那么环卫工人会累趴的。。。】(例子举得不恰当还望见谅,只是帮助理解~)

随着IE7的发布,其javascript引擎的垃圾收集例程改变了工作方式:触发垃圾收集的变量分配、字面量和(或)数组元素的临界值被调整为动态修正。IE7中的各项临界值在初始化时与IE6相等。如果例程回收的内存分配量低于15%,则变量 、字面量和(或)数组元素的临界值就会加倍。如果例程回收了85%的内存分配量,则将各种临界重置会默认值。这一看似简单的调整,极大地提升了IE在运行包含大量javascript的页面时的性能。

事实上,在有的浏览器中可以触发垃圾收集过程,但不建议这样做。在IE中,调用window.CollectGarbage()方法会立即指向垃圾收集,在Opera7及更高版本中,调用widnow.opera.collect()也会启动垃圾收集例程。

三、管理内存

确保占用最少内存可以让页面获得更好的性能,最好通过将其值设置为null来释放其引用——这个做法叫做解除引用(dereferencing)。这一做法是用于大多数全局变量和全局对象的属性。局部变量会在他们执行环境时自动被解除引用,如下面这个例子所示:

 function createPerson (name) {
var localPerson = new Object();
localPerson.name = name;
return localPerson;
};
var gllbalPerson = createPerson("Nicholas"); // 手工解除globalPerson的引用
globalPerson = null;

最后一 行代码就是解除引用。

解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

就相当于你把垃圾从家里拿出来扔到小区的垃圾桶,垃圾只是脱离了你家这个执行环境,但是并未被垃圾场回收,只有等下一个打扫周期,勤劳的环卫工人用垃圾车拉走到垃圾场,才算是将其回收。(例子举得不恰当还望见谅,只是帮助理解~)

从头开始学JavaScript (十)——垃圾收集的更多相关文章

  1. 从头开始学JavaScript (十二)——Array类型

    原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = ne ...

  2. 从头开始学JavaScript (十一)——Object类型

    原文:从头开始学JavaScript (十一)--Object类型 一.object类型 一个object就是一系列属性的集合,一个属性包含一个名字(属性名)和一个值(属性值). object对于在应 ...

  3. 从头开始学JavaScript (九)——执行环境和作用域

    原文:从头开始学JavaScript (九)--执行环境和作用域 一.执行环境:定义了变量或者函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有与之关联的变量对象. 变量对象:保存着环境中 ...

  4. 从头开始学JavaScript (八)——变量

    原文:从头开始学JavaScript (八)--变量 一.变量分类: 基本类型值:null.undefined.number.string.Boolean: 引用类型值:保存在内存中的对象,如:Obj ...

  5. 从头开始学JavaScript (七)——函数

    原文:从头开始学JavaScript (七)--函数 一.return 函数在执行完return之后停止并立即退出. return返回值:与return: 如下两个例子: function sum(n ...

  6. 从头开始学JavaScript (六)——语句

    原文:从头开始学JavaScript (六)--语句 一.条件分支语句:if 基本格式: if (<表达式1>){    <语句组1>}else if (<表达式2> ...

  7. 从头开始学JavaScript (五)——操作符(二)

    原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:*      乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscri ...

  8. 从头开始学JavaScript (四)——操作符

    原文:从头开始学JavaScript (四)--操作符 一.一元操作符 1.自增自减操作符:分为前置型和后置型: 前置型:++a;--a; 后置型:a++;a--; 例: <script typ ...

  9. 从头开始学JavaScript (二)——变量及其作用域

    原文:从头开始学JavaScript (二)--变量及其作用域 一.变量 ECMAscript变量是松散型变量,所谓松散型变量,就是变量名称可以保存任何类型的数据,每个变量仅仅是一个用于保存值的占位符 ...

随机推荐

  1. 《Java程序书面采访猿收藏》之 instanceof的作用是什么

    instanceof它是Java二元运算语言,它的作用是推断对象变量引用被指向的类型是一类(或接口.抽象类.父亲)示例.即,对象是否是它的一个实例离开它的类的权.返回boolean数据类型. 常见的使 ...

  2. 单选框和下拉框的jquery操作

    单选框 <input type="radio" name="rdSendType" value="email" checked=&qu ...

  3. android判断是否含有某权限

    boolean has_permission = (PackageManager.PERMISSION_GRANTED == pkm.checkPermission("android.per ...

  4. HDU 4313 Matrix

    水题:在一个双连通的树上有一些点很有破坏性,我们要把这些带破环性的点隔开,就是破坏一些边使这些点之间不连通,破坏一条边需要一点时间,问最少需要多少时间(同一时间只能破坏一个地方,且忽略位置转移的时间) ...

  5. 【Linux探索之旅】第一部分第六课:Linux如何安装在虚拟机中

    内容简介 1.第一部分第六课:Linux如何安装在虚拟机中 2.第二部分第一课预告:终端Terminal,好戏上场 Linux如何安装在虚拟机中 虽然我们带大家一起在电脑的硬盘上安装了Ubuntu这个 ...

  6. android中获取屏幕的信息

    获取屏幕信息比较简单,可以通过android的sdk自带的工具类DisplayMetrics.话不多说,上代码: // 获取屏幕的信息 DisplayMetrics dm = new DisplayM ...

  7. 【Android基础】listview控件的使用(4)-----自定义布局的listview的使用

    前面我介绍了listview控件的不同用法,但是这些用法在实际的开发项目中是不足以满足需求的,因为前面的几种用法只能简单的显示文本信息,而且布局都比较单一,很难做出复杂的结果,在实际的开发项目中,90 ...

  8. SDUTOJ 1298 活动选择

    #include<iostream> #include<memory.h> using namespace std; int a[105],b[105],c[105],d[10 ...

  9. Spring.Net控制翻转、依赖注入、面向切面编程

    Spring.Net快速入门:控制翻转.依赖注入.面向切面编程 Spring.Net主要功能: 1.IoC:控制翻转(Inversion of Control)  理解成抽象工厂翻转控制:就是创建对象 ...

  10. MS Open Tech 技术团队构建可靠的Windows版Redis

    可靠的Windows版Redis 副标题: 评论更精彩,教你怎么解决64位Windows版Redis狂占C盘的问题. MS Open Tech 技术团队最近花了很多时间来测试最新构建的Windows版 ...