译者前言

  原文地址:Memory leaks  

  最近简单了解了下JavaScript的闭包和垃圾回收机制(GC),这中间也不得不接触内存泄露这个概念。然后不小心找到了这篇文章,看下来后理解了不少东西,于是译之与大家分享。

  在JavaScript中,我们很少考虑到内存管理,但是它又是真实存在的。当我们创建一个变量,接着使用它们,然后浏览器的垃圾回收机制对它们进行回收。

  虽然我们很少考虑内存管理,但是当应用程序越来越复杂并且ajax化之后,我们打开一个网页,过段时间发现浏览器消耗的内存不断增大,很有可能是因为内存泄露,这时我们不得不考虑内存管理。

JavaScript的内存管理

  JavaScript内存管理的核心也就是JavaScript垃圾回收机制,而存在在内存中的数据包括堆栈中的数据(局部变量,正在被调用的方法的参数)以及全局变量;而对象如果被引用或者存在在一个引用链中时,也会存在在内存中。关于这点可以参考JavaScript垃圾回收机制。

  下面再举个GC的例子:

function Menu(title) {
  this.title = title
  this.elem = document.getElementById('id')
}

var menu = new Menu('My Menu')

document.body.innerHTML = ''  // (1)

menu = new Menu('His menu') // (2)

  内存结构如下:

  在step(1)后,body.innerHTML被清空了,所以它的子节点都被移除了。但是元素#id是个例外,它依然能通过menu.elem访问,所以它依然存在在内存中,当然如果你无法访问它的父节点,因为它被移除了。

  单个的dom元素可能存在在内存中哪怕它的父节点已经被移除。

  在step(2)后,window.menu被重新赋值引用,所以原来的menu不可访问了,于是自动被GC回收。

  而闭包经常会引起循环引用:

function setHandler() {

  var elem = document.getElementById('id')

  elem.onclick = function() {
    // ...
  }

}

  dom元素elem通过onclick引用了一个function,而这个function内部也能引用外部作用域里的dom变量elem。

  甚至onclick函数里没有代码,该循环引用同样成立。而一些像addEventListener/attachEvent的方法也会形成类似的循环引用。

内存泄露

  当一个对象不再被引用,但是浏览器由于某些原因并没有释放内存,这时就会引起内存泄露。浏览器问题,浏览器的插件问题,或者我们自己的代码问题都可能引起内存泄露。

  在前面垃圾回收机制一文中我们了解,在IE8以下时,dom对象的循环引用就会引起内存泄露(更进一步讲,其实是COM对象)

function setHandler() {
  var elem = document.getElementById('id')
  elem.onclick = function() { /* ... */ }
}

  dom对象外,任何的COM对象包括XMLHttpRequest都会引起内存泄露。

  IE的内存泄露的解决方式是打破循环引用。

  我们把dom元素elem赋值为null,所以onclick里的function不会再引用elem,所以这个循环被打破了。

  关于XmlHttpRequest的内存管理和泄露:

  以下的代码在IE9以下完美泄露...

var xhr = new XMLHttpRequest() // or ActiveX in older IE

xhr.open('GET', '/server.url', true)

xhr.onreadystatechange = function() {
  if(xhr.readyState == 4 && xhr.status == 200) {
    // ...
  }
}

xhr.send(null)

  让我们来看看内存树:

  

  • JQuery中针对内存泄露的措施以及新的泄露

  jQuery这块还没仔细研究过,略...

  在chrome开发者工具栏中,有个timeline,能或多或少检测内存泄露。

(译)JavaScript内存泄露的更多相关文章

  1. 4类 JavaScript 内存泄露及如何避免

    原文:4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them笔记:涂鸦码龙 译者注:本文并没有逐字逐句的翻译,而是把我认为重要 ...

  2. JavaScript内存泄露,闭包内存泄露如何解决

    本文原链接:https://cloud.tencent.com/developer/article/1340979 JavaScript 内存泄露的4种方式及如何避免 简介 什么是内存泄露? Java ...

  3. [ Javascript ] 内存泄露以及循环引用解析

    内存泄露 在javascript中,我们非常少去关注内存的管理. 我们创建变量,使用变量,浏览器关注这些底层的细节都显得非常正常. 可是当应用程序变得越来越复杂而且ajax化之后,或者用户在一个页面停 ...

  4. 常见的几种JavaScript内存泄露

    总结一下常见的几种JavaScript内存泄露: 1.意外的全局变量 全局变量属于window对象,所以只会随着window销毁才会销毁. 2.console.log() conaole.log()函 ...

  5. Javascript内存泄露

    在过去一些的时候,Web开发人员并没有太多的去关注内存泄露问题.那时的页面间联系大都比较简单,并主要使用不同的连接地址在同一个站点中导航,这样的设计方式是非常有利于浏览器释放资源的.即使Web页面运行 ...

  6. 【翻译】JavaScript内存泄露

    原文地址:http://javascript.info/tutorial/memory-leaks#tools 我们在进行JavaScript开发时,很少会考虑内存的管理.JavaScript中变量的 ...

  7. [转]常见的JavaScript内存泄露

    什么是内存泄露 内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制, ...

  8. JavaScript 内存泄露以及如何处理

    一.前言 一直有打算总结一下JS内存泄露的方面的知识的想法,但是总是懒得提笔. 富兰克林曾经说过:懒惰,像生鏽一样,比操劳更能消耗身体,经常用的钥匙总是亮闪闪的.安利一下,先起个头. 二.内存声明周期 ...

  9. 常见的 JavaScript 内存泄露

    什么是内存泄露 指由于疏忽或错误造成程序未能释放已经不再使用的内存.内存泄漏并非指内存在物理上的消失, 而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造 ...

随机推荐

  1. 学习HTML5必读之《HTML5设计原理》

    引子:很久前看过的一遍受益匪浅的文章,今天再次转过来,希望对学习HTML5的朋友有所帮助. 今天我想跟大家谈一谈HTML5的设计.主要分两个方面:一方面,当然了,就是HTML5.我可以站在这儿只讲HT ...

  2. MySQL 存储过程实例 与 ibatis/mybatis/hibernate/jdbc 如何调用存储过程

    虽然MySQL的存储过程,一般情况下,是不会使用到的,但是在一些特殊场景中,还是有需求的.最近遇到一个sql server向mysql迁移的项目,有一些sql server的存储过程需要向mysql迁 ...

  3. SQLServerDBA十大必备工具---让生活轻松点(转)

    曾经和一些DBA和数据库开发人员交流时,问他们都用过一些什么样的DB方面的工具,大部分人除了SSMS和Profile之外,基本就没有使用过其他工具了: 诚然,SSMS和Profile足够强大,工作的大 ...

  4. Redis系列(一)——简介及安装

    摘自:redis中文网(http://www.redis.net.cn/) 参考:http://www.cnblogs.com/hoojo/p/4466024.html,http://keenwon. ...

  5. pageX和pageY

    pageX() 属性是鼠标指针的位置,相对于文档的左边缘. pageY() 属性是鼠标指针的位置,相对于文档的上边缘. 例1 $(document).mousemove(function(e){ $( ...

  6. 基于51单片机+DAC0832的信号发生器

    最近帮别人设计一个毕业设计,做一个多种信号发生器(四种波形:方波.三角波.锯齿波.梯形波),现在贴上来给大家参考,如果有错误的地方,望指出~ 下面先贴上仿真的电路图(仿真的软件是Protuse,上传一 ...

  7. OpenCV 之 数字图像

    1  数字图像 数字图像可看作一个数值矩阵, 其中的每个元素代表一个像素点,如下图所示: 2  存储 M行N列图像的存储位数: b = M * N * k   ( L=2k, l ∈ [0, L-1] ...

  8. 最长上升子序列(LIS)模板

    最长递增(上升)子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增(上升)子序列. 考虑两个数a[x ...

  9. 第12章 纤程(Fiber)

    12.1 纤程对象的介绍 (1)纤程与线程的比较 比较 线程(Thread) 纤程(Fiber) 实现方式 是个内核对象 在用户模式中实现的一种轻量级的线程,是比线程更小的调度单位. 调度方式 由Mi ...

  10. java 20 - 9 带有缓冲区的字节输出流和字节输入流

    由之前字节输入的两个方式,我们可以发现,通过定义数组读取数组的方式比一个个字节读取的方式快得多. 所以,java就专门提供了带有缓冲区的字节类: 缓冲区类(高效类) 写数据:BufferedOutpu ...