关于JavaScript内存泄漏的质疑

近几天看了些关于JavaScript内存管理的文章,相对于Java JVM的内存管理,显得简单些。

在学习的过程中,发现有不少网友谈到了循环引用,说循环引用会造成内存泄漏,垃圾回收器无法回收。

实际上,并没有这么可怕,根据小菜目前的了解,这种循环引用造成的内存泄漏,仅仅会发生在低版本的IE浏览器上,现代浏览器是不会这么蠢的。

举个例子,网络上流行的说法大致有如下两种:

 1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <meta charset="utf-8">
 5     <meta name="viewport" content="width=640, initial-scale=0.5, user-scalable=no" />
 6     <title>循环引用内存分析</title>
 7     <style>
 8     </style>
 9   </head>
10   <body>
11     <input type="button" onclick="Problem();" value="call Problem">
12     <input type="button" onclick="MyBindEvent();" value="call MyBindEvent">
13   </body>
14   <script>
15     //闭包引起的隐式循环引用
16     function MyBindEvent(){
17       var obj=document.createElement("div");
18       obj.onclick=function(){
19         //Even if it‘s a empty function
20       };
21     }
22
23     //显式循环引用
24     function Problem() {
25       var objA = new Object();
26       var objB = new Object();
27
28       objA.someOtherObject = objB;
29       objB.anotherObject = objA;
30     }
31   </script>
32
33 </html>

一个简单的页面,上边两个按钮,分别调用两个会造成内存泄漏的方法。

借助于Chrome浏览器的Profiles功能,生成内存快照,然后对比,发现这两种写法在谷歌浏览器下均没有泄漏问题。

具体做法是:

  1. 打开页面不做任何操作,直接生成页面内存快照。
  2. 点击按钮,然后再次生成内存快照。
  3. 对比两次内存变化。

不断重复这个过程,生成7、8个快照,趋于稳定,会发现往后内存根本没有变化。

每次生成快照之前,都会强制执行GC(垃圾回收),说明我们每次构造的循环引用,马上被回收了,所以不会出现在快照中。

接下来从理论角度说说为什么应该被回收。

因为这些循环引用,说白了都是无效引用。可以简单理解为:只有从栈区发起的引用才是有效的。本例中的引用,是堆区对象的互相引用,虽然引用计数不为0,但是不可到达,在回收内存时直接就被消灭了。

再深入了说,低版本IE浏览器采用的是引用计数机制回收内存,互相引用造成对方计数互不为0,导致无法回收。

而现代浏览器,采用的是Cheney算法,大致就是把内存分为两份,不断的来回复制,这样那些不可到达的对象,就无法复制,自然被回收了。

栈区、静态、常量之类的字眼,一般是代表root(根)区,只有从这些地方发出的引用,才是可到达的,有效的。

时间: 2024-10-18 02:53:32

关于JavaScript内存泄漏的质疑的相关文章

javaScript内存泄漏

first: 先理解我们的基本概念,什么是内存泄漏: 答: 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak) 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分

javascript 内存泄漏的学习

概念 内存泄漏: 用动态存储分配函数动态开辟的空间,在使用完毕后未释放, 木有任何指针指向他,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存空间使用完毕之后未回收, 占着茅坑不**)即所谓内存泄漏. 等所有内存都被占完之后, 系统就跪了. 内存分配方式 说道内存泄露,就不得不谈到内存分配的方式.内存分配有三种方式,分别是: 一.静态分配( Static Allocation ):静态变量和全局变量的分配形式.如果把房间看做一个程序,我们可以把静态分配的内存当成是房间里的耐用家具

JavaScript学习总结(二十三)——JavaScript 内存泄漏教程

参考教程:http://www.ruanyifeng.com/blog/2017/04/memory-leak.html 一.什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃. 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak). 有些语言(比如 C 语言)必须手动释放内存,程序员负责内存管

JavaScript 内存泄漏教程

一.什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃. 不再用到的内存,没有及时释放,就叫做内存泄漏(memory leak). 有些语言(比如 C 语言)必须手动释放内存,程序员负责内存管理. char * buffer; buffer = (char*) malloc(42); // Do somethin

了解 JavaScript 应用程序中的内存泄漏

简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许多功能无需考虑内存管理即可实现,但却忽略了它可能在程序中带来重大的问题.不当清理的对象可能会存在比预期要长得多的时间.这些对象继续响应事件和消耗资源.它们可强制浏览器从一个虚拟磁盘驱动器分配内存页,这显著影响了计算机的速度(在极端的情形中,会导致浏览器崩溃). 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在.在最近几

JavaScript中的内存泄漏以及如何处理

随着现在的编程语言功能越来越成熟.复杂,内存管理也容易被大家忽略.本文将会讨论JavaScript中的内存泄漏以及如何处理,方便大家在使用JavaScript编码时,更好的应对内存泄漏带来的问题. 概述 像C语言这样的编程语言,具有简单的内存管理功能函数,例如malloc( )和free( ).开发人员可以使用这些功能函数来显式地分配和释放系统的内存. 当创建对象和字符串等时,JavaScript就会分配内存,并在不再使用时自动释放内存,这种机制被称为垃圾收集.这种释放资源看似是"自动"

JavaScript 中的内存泄漏

JavaScript 是一种垃圾收集式语言,这就是说,内存是根据对象的创建分配给该对象的,并会在没有对该对象的引用时由浏览器收回.JavaScript 的垃圾收集机制本身并没有问题,但浏览器在为 DOM 对象分配和恢复内存的方式上却有些出入. Internet Explorer 和 Mozilla Firefox 均使用引用计数来为 DOM 对象处理内存.在引用计数系统,每个所引用的对象都会保留一个计数,以获悉有多少对象正在引用它.如果计数为零,该对象就会被销毁,其占用的内存也会返回 给堆.虽然

JavaScript的闭包和内存泄漏问题

闭包 JavaScript中必须提到的功能最强大的抽象概念之一:闭包.它究竟是做什么的呢? 1 function makeAdder(a) { 2 return function(b) { 3 return a + b; 4 } 5 } 6 var x = makeAdder(5); 7 var y = makeAdder(20); 8 x(6); // 11 9 y(7); // 27 makeAdder这个名字本身应该能说明函数是用来做什么的:他创建了一个新的adder函数,这个函数自身带有

前端开发中javascript闭包会引发内存泄漏么?

本文主要是和大家一起来讨论下javascript的闭包会造成内存泄漏吗?希望通过本文的分享对大家学习javascript有所帮助.  在谈内存泄漏这个问题之前先看看JavaScript的垃圾收集机制,JavaScript 具有自动垃圾收集机制,就是找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间).常用的的方法有两种,即标记清楚和引用计数.  标记清除  JavaScript 中最常用的垃圾收集方式是标记清除(mark-and-s