谈谈JavaScript中的垃圾回收机制

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

  在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理。

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

  具体到浏览器中的实现,则通常有两个策略,分别为标记清除和引用计数。

一、标记清除

  JavaScript 中最常用的垃圾收集方式是标记清除(mark-and-sweep)。当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。而当变量离开环境时,则将其标记为“离开环境”。

  垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。可以使用任何标记方式,比如,可以通过翻转某个特殊的位来记录一个变量何时进入环境, 或者使用一个“进入环境的”变量列表及一个“离开环境的”变量列表来跟踪哪个变量发生了变化。

  然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。

  最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

二、引用计数

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

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

  当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。

  这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。

  存在的问题:只要在 IE 中涉及 COM(Component Object Model,组件对象模型)对象,就会存在循环引用的问题。如下面代码所示:

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 意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。

三、管理内存

  确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据。

  一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个做法叫做解除引用(dereferencing)。

  这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动被解除引用,如下面这个例子所示:

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

   变量 globalPerson 取得了 createPerson()函数返回的值。在 createPerson() 函数内部,我们创建了一个对象并将其赋给局部变量localPerson,然后又为该对象添加了一个名为 name 的属性。最后,当调用这个函数时,localPerson 以函数值的形式返回并赋给全局变量 globalPerson。

  由于 localPerson 在 createPerson()函数执行完毕后就离开了其执行环境,因此无需我们显式地去为它解除引用。

  但是对于全局变量 globalPerson 而言,则需要我们在不使用它的时候手工为它解除引用,这也正是上面例子中最后一行代码的目的。

以上就是谈谈JavaScript中的垃圾回收机制的详细内容,更多关于JavaScript 垃圾回收的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript 垃圾回收机制分析

    在公司经常会听到大牛们讨论时说道内存泄露神马的,每每都惊羡不已,最近精力主要用在了Web 开发上,读了一下<JavaScript高级程序设计>(书名很唬人,实际作者写的特别好,由浅入深)了解了一下JavaScript垃圾回收机制,对内存泄露有了一定的认识. 和C#.Java一样JavaScript有自动垃圾回收机制,也就是说执行环境会负责管理代码执行过程中使用的内存,在开发过程中就无需考虑内存分配及无用内存的回收问题了.JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其

  • 跟我学习javascript的垃圾回收机制与内存管理

    一.垃圾回收机制-GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存. 原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存. JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行. 不再使用的变量也就是生命周期结束的变量,当然只可能是局部变量,全局变量的生

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

    如果我们想要优化性能,首先我们必须得了解JavaScript中的垃圾回收机制,这样可以将很多没有被使用到的变量从内存中清除掉,腾出更多的内存空间,给别的变量分配内存空间. JavaScript中的垃圾回收机制 引言 本篇文章将讲解一下javascript的垃圾回收机制.同时,我们必须先具备作用域链的概念,不懂的小伙伴可以先花5分钟观看一下这篇文章,简单了解一下作用域链的知识--从零开始讲解JavaScript中作用域链的概念及用途 正文 一.垃圾回收机制 在JavaScript中,具有自动垃圾回

  • 浅谈JavaScript 执行环境、作用域及垃圾回收

    执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有一个与之关联的变量对象. 全局执行环境是最外围的一个执行环境.根据JavaScript实现所在的宿主环境不同,表示执行环境的对象也不一样.在Web浏览器中,全局执行环境被认为是window对象.因此,所有的全局变量和函数都是作为window对象的属性和方法创建的. 变量对象:环境中定义的所有变量和函数都保存在这个对象中. 作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链.作用域链的用途是保证对执行环

  • js的新生代垃圾回收知识点总结

    在进行老生代的标记清除法回收以前,还会有一个新生代的垃圾回收算法执行. 新生代和老生代 所谓新生代,指的是新产生的对象:老生代就是经历过新生代垃圾回收后还"存活"下来的对象. 新生代的垃圾回收算法 Scavenge GC 算法很简单: 1. 我们维护一个列表,老生代对象每次指向一个新生对象的时候,记录下来:每次删除指向的时候,删除记录.(这样我们就知道新生代对象里面,哪些对象是存活的了) 2. 我们把新生代对象的内存平均分开 2 份空间From 和 To 3. 每当有新生对象诞生,就会

  • JS闭包、作用域链、垃圾回收、内存泄露相关知识小结

    补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的特性 闭包有三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收 闭包的定义及其优缺点 闭包 是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量 闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露. 闭包是javascript

  • 深入理解 JS 垃圾回收

    前言 JS之memoization,memoization 的原理是以参数作为 key,函数结果作为 value, 用对象进行缓存起来,以内存空间换 CPU 执行事件.memoization 的潜在陷阱即是严格意义的缓存有着完善的过期策略,而普通对象的键值对并没有. 用闭包进行缓存的对象的内存空间,不会在函数执行完后被清除,在执行量大和参数多样性的情况下,会造成内存占用且得不到释放. 于是,本篇文章就来讲讲 JS 的垃圾回收. JS 的垃圾回收机制的基本原理是: 找出那些不再继续使用的变量,然后

  • JavaScript中的垃圾回收与内存泄漏示例详解

    前言 程序的运行需要内存.只要程序提出要求,操作系统或者运行时就必须供给内存.所谓的内存泄漏简单来说是不再用到的内存,没有及时释放.为了更好避免内存泄漏,我们先介绍Javascript垃圾回收机制. 在C与C++等语言中,开发人员可以直接控制内存的申请和回收.但是在Java.C#.JavaScript语言中,变量的内存空间的申请和释放都由程序自己处理,开发人员不需要关心.也就是说Javascript具有自动垃圾回收机制(Garbage Collecation). 一.垃圾回收的必要性 下面这段话

  • 对于js垃圾回收机制的理解

    原理 找到不再被使用的变量,然后释放其占用的内存,但这个过程不是时时的,因为其开销比较大, 所以垃圾回收器会按照固定时间间隔周期性的执行 回收方式 a.标记清除 当变量进入环境时,将这个变量标记为"进入环境";当变量离开环境时,则将其标记为"离开环境". 标记"离开环境"的就回收内存 b.引入计数(低级浏览器) 当变量声明,第一次赋值时记为1,然后当这个变量值改变时,记录为0,将计数为0的回收 内存泄露 a.意外的全局变量引起的内存泄露 原因:

  • 谈谈JavaScript中的垃圾回收机制

    JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. 在编写 JavaScript 程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理. 这种垃圾收集机制的原理其实很简单:找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间), 周期性地执行这一操作. 具体到浏览器中的实现,则通常有两个策略,分别为标记清除和引用计数. 一.标记清除 JavaScri

  • 基于java中stack与heap的区别,java中的垃圾回收机制的相关介绍

    #. 在java中有两类内存.分别称为stack(堆栈)和heap(堆). stack是程序内存空间,因此所有的基本类型和对象的引用是存在stack中. heap是java虚拟机储存对象的,它是一个巨大的内存,当你创造一个对象,java虚拟机把对象放入heap中,把创造的对象的地址放入stack中. 因此,基本类型.对象的引用储存在stack中:对象储存在heap中. #. java中的垃圾回收机制 当你new一个新的对象,java分配必需的内存.当你用完一个对象时,java的垃圾回收器为你把内

  • C#开发中的垃圾回收机制简析

    GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是GC的第一次出现.Lisp的程序员认为内存管理太重要了,所以不能由程序员自己来管理.但后来的日子里Lisp却没有成气候,采用内存手动管理的语言占据了上风,以C为代表.出于同样的理由,不同的人却又不同的看法,C程序员认为内存管理太重要了,所以不能由系统来管理,并且讥笑Lisp程序慢如乌龟的运行速度.的

  • 解读PHP中的垃圾回收机制

    PHP的基本GC概念 PHP语言同其他语言一样,具有垃圾回收机制.那么今天我们要为大家讲解的内容就是关于PHP垃圾回收机制的相关问题.希望对大家有所帮助.PHP strtotime应用经验之谈PHP memory_get_usage()管理内存PHP unset全局变量运用问题详解PHP unset()函数销毁变量教你快速实现PHP全站权限验证一.PHP 垃圾回收机制(Garbage Collector 简称GC) 在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾.PHP会将其在内存中

  • php中session垃圾回收机制

    在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾.PHP会将其在内存中销毁:这是PHP的GC垃圾处理机制,防止内存溢出. GC的工作就是扫描所有的Session信息,用当前时间减去session最后修改的时间,同session.gc_maxlifetime参数进行比较,如果生存时间超过gc_maxlifetime(默认24分钟),就将该session删除. 当一个有效的请求发生时,PHP 会根据全局变量 session.gc_probability和session.gc_divisor

  • 一文带你回顾Java中的垃圾回收机制

    目录 介绍 重要条款: 使对象符合 GC 条件的方法 请求JVM运行垃圾收集器的方式 定稿 让我们举一个真实的例子,在那里我们使用垃圾收集器的概念. 现在获得正确的输出: 总结 介绍 在 C/C++ 中,程序员负责对象的创建和销毁.通常程序员会忽略无用对象的销毁.由于这种疏忽,在某些时候,为了创建新对象,可能没有足够的内存可用,整个程序将异常终止,导致OutOfMemoryErrors. 但是在 Java 中,程序员不需要关心所有不再使用的对象.垃圾回收机制自动销毁这些对象. 垃圾回收机制是守护

  • Java 中的垃圾回收机制详解

    目录 介绍 重要条款: 使对象符合 GC 条件的方法 请求JVM运行垃圾收集器的方式 定稿 总结 介绍 在 C/C++ 中,程序员负责对象的创建和销毁.通常程序员会忽略无用对象的销毁.由于这种疏忽,在某些时候,为了创建新对象,可能没有足够的内存可用,整个程序将异常终止,导致OutOfMemoryErrors. 但是在 Java 中,程序员不需要关心所有不再使用的对象.垃圾回收机制自动销毁这些对象. 垃圾回收机制是守护线程的最佳示例,因为它始终在后台运行. 垃圾回收机制的主要目标是通过销毁无法访问

  • 简单讲解Lua中的垃圾回收机制

    Lua使用基于被内置在Lua某些算法的垃圾收集自动内存管理.可以自动内存管理的结果,作为一个开发者: 没有必要担心的对象分配内存. 无需释放他们时,不再需要可将其设置为nil. Lua使用运行不时收集死的对象时,不再从Lua程序中访问垃圾收集器. 所有对象,包括表,用户数据,函数,线程,字符串等受自动内存管理. Lua使用增量标记和使用两个数字来控制其垃圾回收周期即垃圾收集暂停和垃圾收集器的步骤事半功倍清除收集器.这些值是在百分比和100的值是常等于1. 垃圾收集暂停 垃圾收集停顿被用于控制多长

  • 详谈.net中的垃圾回收机制

    1. 自动内存管理和GC 在原始程序中堆的内存分配是这样的:找到第一个有足够空间的内存地址(没被占用的),然后将该内存分配.当程序不再需要此内存中的信息时程序员需要手动将此内存释放.堆的内存是公用的,也就是说所有进程都有可能覆盖另一进程的内存内容,这就是为什么很多设计不当的程序甚至会让操作系统本身都down掉.我们有时碰到的程序莫名其妙的死掉了(随机现象),也是因为内存管理不当引起的(可能由于本身程序的内存问题或是外来程序造成的).另一个常见的实例就是大家经常看到的游戏的Trainer,他们通过

随机推荐