JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。

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

1.标记清除

  JavaScript中最重用的垃圾收集方式是标记清除(mark-and-sweep)。Take is cheap, let me show you the code.

  当运行addTen()这个函数的时候,就是当变量进入环境时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。

1 function addTen(num){
2     var sum += num;  //垃圾收集已将这个变量标记为“进入环境”。
3     return sum;      //垃圾收集已将这个变量标记为“离开环境”。
4 }
5 addTen(10);  //输出20

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

以下举一个简单释放内存例子:

var user = {name : 'scott', age : '21', gender : 'male'}; //在全局中定义变量,标记变量为“进入环境”

user = null;  //最后定义为null,释放内存

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

1.引用计数

  另一种不太常见的垃圾收集策略叫做引用计数(reference counting)。引用计数的含义是跟踪记录每个值被引用的次数。

  当声明了一个变量并将一个引用类型值赋值该变量时,则这个值的引用次数就是1.如果同一个值又被赋给另外一个变量,则该值得引用次数加1。相反,如果包含对这个值引用的变量又取 得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 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。

  假如这个函数被重复多次调用,就会导致大量内存得不到回收。为此放弃了引用计数方式,转而采用标记清除来实现其垃圾收集机制。可是,引用计数导致的麻烦并未就此终结。

  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高级程序设计》

 

转载于:https://www.cnblogs.com/scottjeremy/p/6870729.html

JavaScript垃圾收集-标记清除和引用计数相关推荐

  1. js垃圾回收的标记清理与引用计数

    js是使用垃圾回收的语言,也就是说执行环境负责在代码执行时管理内存.js为开发者卸下跟踪内存这个负担,通过自动内存管理实现内存分配和闲置资源回收.基本思路很简单:确定哪个变量不会再使用,然后释放它所占 ...

  2. python垃圾回收机制为什么标记能解决循环引用问题_python 关于循环引用以及标记清除的问题...

    1 在循环引用的情况下,引用计数就不好事了,这时候就需要用到标记清除 循环引用的危害: 会造成内存溢出,因为循环引用计数不可能为零 解决方法: 标记清除 2 关于标记清除的效率问题(低) 引用计数引用 ...

  3. Python的垃圾回收机制(引用计数+标记清除+分代回收)

    一.写在前面: 我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念.在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyOb ...

  4. 【JVM基础】垃圾回收算法详解(引用计数、标记、清除、压缩、复制)

    前言 笔记参考 Java 全栈知识体系.星羽恒.星空茶 文章目录 前言 垃圾回收概述 引用计数法 案例 优点 缺点 标记.清除.压缩 标记 清除 压缩 标记清除算法 优点 缺点 标记压缩算法 优点 缺 ...

  5. 67.Java垃圾收集机制\对象引用\垃圾对象的判定\垃圾收集算法\标记—清除算法\标记—整理算法\分代收集\垃圾收集器\性能调优

    67.Java垃圾收集机制 67.1.对象引用 67.2.垃圾对象的判定 67.3.垃圾收集算法 67.3.1.标记-清除算法 67.3.2.标记-整理算法 67.3.3.分代收集 67.4.垃圾收集 ...

  6. 26 Java GC算法 垃圾收集器、标记 -清除算法、复制算法、标记-压缩算法、分代收集算法

    26.Java GC算法 垃圾收集器 1.1.1标记 -清除算法 1.1.2复制算法 1.1.3标记-压缩算法 1.1.4分代收集算法 26.Java GC算法 垃圾收集器 概述 垃圾收集 Garba ...

  7. 2、垃圾回收算法(标记清除算法、复制算法、标记整理算法和分代收集算法),各种垃圾收集器讲解(学习笔记)

    2.垃圾回收概述 2.1.垃圾回收算法 2.1.1.垃圾回收算法-标记清除算法 2.1.2.垃圾回收算法–复制算法 2.1.3.垃圾回收算法–标记整理算法和分代收集算法 2.1.4.垃圾回收算法–Se ...

  8. JVM系列(十一) 垃圾收集器之 Concurrent Mark Sweep 并发标记清除

    垃圾收集器之 Concurrent Mark Sweep 并发标记清除 上几篇文章我们讲解了单线程垃圾收集器 Serial/SerialOld ,多线程垃圾收集器 Parallel Scavenge/ ...

  9. java cms 垃圾回收_Java 9 或将放弃 CMS(并发标记清除垃圾收集器)

    原标题:Java 9 或将放弃 CMS(并发标记清除垃圾收集器) 近日,JEP 291 再次被 Java 开发团队提上日程.先来看看该 JEP. JEP 291: Deprecate the Conc ...

  10. js 内存引用计数_快速内存管理–自动引用计数

    js 内存引用计数 In this tutorial, we'll be covering Swift memory management and learn about Automatic Refe ...

最新文章

  1. 500 - Internal server error.
  2. 【集合论】序关系 ( 偏序集元素之间的关系 | 可比 | 严格小于 | 覆盖 | 哈斯图 )
  3. HDU1250 Hat's Fibonacci 大数斐波那契数列
  4. Timer定时器Demo
  5. dialog能提交数据吗_你的数据库,能撑起多少并发,有数吗?
  6. 【2019牛客暑期多校训练营(第三场)- A】Graph Games(思维,对边分块)
  7. Ubuntu下使用AMD APP编写OpenCL程序
  8. (转)关键字const有什么含意?
  9. 图片上传工具 java_图片上传工具类-fileUtil
  10. 变形二叉树中节点的最大距离(树的最长路径)——非递归解法
  11. python 用 __all__ 暴露接口
  12. ELK官方文档收集Kibana监视数据编辑
  13. 用c语言覆盖前一个字符的值,C/C++笔试题
  14. 边缘计算对于基础架构和运营领导者意味着什么
  15. 网站后台目录扫描工具Dirbuster和御剑(脚本小子的最爱)
  16. 我收藏的PDF电子书第一部分
  17. PRINCE2的含金量如何?
  18. 设备\Device\Harddisk1\DR1 有一个不正确的区块
  19. 解读 | 数据分析师(含转行)的面试简历如何写?
  20. 从JDK源码看Writer

热门文章

  1. NJUPT_CTF easychallenge 解题脚本
  2. Find命令使用详解及实例分析
  3. Apache简单配置(5)搭建phpcms2007网站+phpBB-3.0论坛
  4. 10月第3周安全回顾:恶意软件肆虐 Web安全重点关注
  5. ADO.NET 对象模型
  6. 两种消息模型: 点对点(queue)发布/订阅(topic)
  7. windows下mysql-8.0.11的安装
  8. opencv4 图像特征匹配_【从零学习OpenCV 4】图像模板匹配
  9. java redirect 超时_java – Spring Security 3.0重定向到超时的页面
  10. Unity 常用API以及C# 工具类的使用