innerHTML引起IE的内存泄漏
内存泄漏常见的原因有三种:
1. 闭包
2. 未解除事件绑定
3. 循环引用DOM元素
除此之外,还有一种泄漏原因少有人知,它和innerHTML有关,不过很容易解决。
出现这种内存泄漏需要有三个条件:
1. 内存中存在一个未加入DOM树的元素
2. 给这个元素设置innerHTML,注意,必须是能创建元素并且绑定了DOM 0级事件
3. 必须在这个元素加入DOM树前设置它的innerHTML
举个例子:
// 创建一个仅存在于内存中的元素var el = document.createElement('div');// 设置innerHTMLel.innerHTML = '<a onclick = "testFn()">Test Link</a>';// 加入DOM树document.body.appendChild(el) |
这种写法很常见对吧,但你根本察觉不到有内存泄漏。唯一的隐患在于,当你在一个相同的页面上频繁地用这种方式设置innerHTML,一次又一次,反反复复,没完没了,好吧,其实也没那么多次,总之是很多次之后,就会出现问题了。
肯定有人会说,谁那么蛋疼地总折腾一个元素,其实在ajax泛滥的时代,经常需要动态更新页面,所以这种情况也并非罕见。
如果实在不信,这里有两个DEMO页面:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head> <title>IE innerHTML Memory Leak Demo</title> <style type = "text/css">
html,body
{
font-family: arial;
font-size: 120%;
} div a
{
font-size: 120%;
display: block;
margin: 5px;
padding: 5px;
border: 2px solid #000;
background-color: lightgreen;
}
</style> <script type = "text/javascript"> var btnStart, btnStop; function init()
{
btnStart = document.getElementById('btnStart');
btnStop = document.getElementById('btnStop');
btnStart.onclick = startLeak;
btnStop.onclick = stopLeak;
} function startLeak()
{
btnStart.disabled = true;
btnStop.disabled = false;
leak();
} function stopLeak()
{
btnStop.disabled = true;
btnStart.disabled = false;
} function leak()
{
if (btnStop.disabled == true)
{
return;
} var str = '';
var i, len = 2000;
for (i = 0; i < len; i++)
{
str += '<a onclick = "test()">Test Link</a>';
} var elem = document.getElementById('testDiv');
if (elem) document.body.removeChild(elem); var elem = document.createElement('div');
elem.id = 'testDiv'; // Oops! Setting .innerHTML first, and _then_ calling .appendChild(..) is asking for a memory leak!
elem.innerHTML = str;
document.body.appendChild(elem); setTimeout(leak, 250);
} function test()
{
alert('Click!');
return false;
} window.onload = init;
</script>
</head> <body>
<h1>IE innerHTML Memory Leak Demo</h1> <p>Upon clicking the "Start Leak" button, a script will execute repeatedly which creates a new <div> element in memory,
sets its innerHTML to a string of 2000 <a> tags with onclick events wired up ('<a onclick = "test()">Test Link</a>'),
and then adds that <div> to the
page.</p> <p>Letting this script run for about 60 seconds, and using Perfmon to monitor memory consumption, you should notice a significant
increase in the amount of memory consumed. To see the same script logic that doesn't leak memory, view the
<a href = "./noleak.html">No Leak Page</a>.</p> <button id = "btnStart">Start Leak</button>
<button id = "btnStop" disabled = "disabled">Stop Leak</button>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head> <title>IE innerHTML Memory Leak Demo (the fix)</title> <style type = "text/css">
html,body
{
font-family: arial;
font-size: 120%;
} div a
{
font-size: 120%;
display: block;
margin: 5px;
padding: 5px;
border: 2px solid #000;
background-color: lightgreen;
}
</style> <script type = "text/javascript"> var btnStart, btnStop; function init()
{
btnStart = document.getElementById('btnStart');
btnStop = document.getElementById('btnStop');
btnStart.onclick = startLeak;
btnStop.onclick = stopLeak;
} function startLeak()
{
btnStart.disabled = true;
btnStop.disabled = false;
leak();
} function stopLeak()
{
btnStop.disabled = true;
btnStart.disabled = false;
} function leak()
{
if (btnStop.disabled == true)
{
return;
} var str = '';
var i, len = 2000;
for (i = 0; i < len; i++)
{
str += '<a onclick = "test()">Test Link</a>';
} var elem = document.getElementById('testDiv');
if (elem) document.body.removeChild(elem); var elem = document.createElement('div');
elem.id = 'testDiv'; // Add the element to the DOM first, and /then/ set .innerHTML to prevent memory from leaking.
document.body.appendChild(elem);
elem.innerHTML = str; setTimeout(leak, 250);
} function test()
{
alert('Click!');
return false;
} window.onload = init;
</script>
</head> <body>
<h1>IE innerHTML Memory Leak Demo (the fix)</h1> <p>Upon clicking the "Start Leak" button, a script will execute repeatedly which creates a new <div> element in memory and
then adds that element to the page. Only <em>after</em> the element has been added to the page, do we set its .innerHTML to a
string to 2000 <a> tags with onclick events wired up ('<a onclick = "test()">Test Link</a>').</p> <p>Letting this script run for about 60 seconds, and using Perfmon to monitor memory consumption, you should notice that,
unlike the <a href = "./leak.html">Leak Page</a>, memory consumption remains relatively constant.</p> <button id = "btnStart">Start Leak</button>
<button id = "btnStop" disabled = "disabled">Stop Leak</button>
</body>
</html>
接着来看怎么解决它:
其实很简单,换个顺序,先把元素加入DOM树,再设置innerHTML。
当然你也可以完全放弃使用innerHTML,这样做好处多多,比如不会存在未解除事件绑定的情况,但貌似完全放弃innerHTML也不现实。。。
innerHTML引起IE的内存泄漏的更多相关文章
- 关于Javascript的内存泄漏问题的整理稿
写了好长时间javascript小功能模块,从来没有关注过内存泄漏问题.记得以前写C++程序的时候,内存泄漏是个严重的问题,我想是时候关注一下了.网上找了篇文章,Mark一下.原文地址:http:// ...
- JS内存泄漏 和Chrome 内存分析工具简介(摘)
原文地址:http://web.jobbole.com/88463/ JavaScript 中 4 种常见的内存泄露陷阱 原文:Sebastián Peyrott 译文:伯乐在线专栏作者 - AR ...
- JavaScript中的内存泄漏以及如何处理
随着现在的编程语言功能越来越成熟.复杂,内存管理也容易被大家忽略.本文将会讨论JavaScript中的内存泄漏以及如何处理,方便大家在使用JavaScript编码时,更好的应对内存泄漏带来的问题. 概 ...
- JavaScript如何工作:内存管理+如何处理4个常见的内存泄漏
摘要: 作者将自己常用的JavaScript模块分享给大家. 原文:JavaScript如何工作:内存管理+如何处理4个常见的内存泄漏 作者:前端小智 Fundebug经授权转载,版权归原作者所有. ...
- 【进阶1-5期】JavaScript深入之4类常见内存泄漏及如何避免(转)
这是我在公众号(高级前端进阶)看到的文章,现在做笔记 https://mp.weixin.qq.com/s/RZ8Lpkyk8lz6z5H8Q8SiEQ 垃圾回收算法 常用垃圾回收算法叫做**标记清除 ...
- JavaScript中的垃圾回收和内存泄漏
摘要: JS内存管理. 作者:浪里行舟 Fundebug经授权转载,版权归原作者所有. 前言 程序的运行需要内存.只要程序提出要求,操作系统或者运行时就必须供给内存.所谓的内存泄漏简单来说是不再用到的 ...
- innerHTML与IE浏览器内存泄露问题
使用 sIEve 扫描和筛选 如果大量使用 JavaScript 和 Ajax 技术开发 Web 2.0 应用程序,您很有可能会遇到浏览器的内存泄漏问题.如果您有一个单页应用程序或者一个页面要处理很多 ...
- How Javascript works (Javascript工作原理) (三) 内存管理及如何处理 4 类常见的内存泄漏问题
个人总结: 1.两种垃圾回收机制: 1)引用标记算法:如果检测到一个对象没有被引用了,就清除它. ***这种算法不能处理循环引用的情况*** 2)标记—清除算法:从根(全局变量)开始向后代变量检测,任 ...
- Chrome 浏览器垃圾回收机制与内存泄漏分析
Chorme 浏览器中的垃圾回收和内存泄漏 垃圾回收 通常情况下,垃圾数据回收分为手动回收和自动回收两种策略. 手动回收策略,何时分配内存.何时销毁内存都是由代码控制的. 自动回收策略,产生的垃圾数据 ...
随机推荐
- [Silverlight 2.0 控制物体绕圆弧运行(C#初探篇)]
我自己写的第一个 Silverlight 2.0 程序 [Silverlight 2.0 控制物体绕圆弧运行(C#初探篇)] 程序运行时:小地球将绕着圆形轨迹做圆周运动. ...
- ios打印frame等格式
1.打印frame:NSLog(@"%@",NSStringFromCGRect(pickerView.frame)); 或者CFShow(NSStringFromCGRect(p ...
- 黑客技术 —— Linux 命令行
很多和正则表达式 re 是一致的: 1. 修改上次执行的命令 删除多余部分: % grep fooo /var/log/auth.log % ^o % grep foo /var/log/auth.l ...
- VC将同一份代码同时编译为Dll和Exe的方法
开发中经常遇到这样的情况,需要开发一个某某功能的接口Dll,但是Dll不能直接调试,你至少需要一个Loader 但是Loader和Dll本身不在同一个工程里,虽然都在本机的话并不影响源码级调试,但是总 ...
- centos安装xen虚拟机并且配置bridge
主要参考的几个官方文档: http://wiki.centos.org/HowTos/Xen/Xen4QuickStart 在centos上安装xen组件并建立dom0 http://wiki.cen ...
- 网易蜂巢(云计算基础服务)MongoDB服务重磅来袭
此文已由作者温正湖授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. MongoDB是目前最为流行的NoSQL数据库,在2017年1月新鲜出炉的数据库权威排行榜上,MongoDB ...
- “玲珑杯”线上赛 Round #17 河南专场 B:震惊,99%+的中国人都会算错的问题(容斥计算)
传送门 题意 略 分析 是一道稍微变形的容斥题目,容斥一般的公式 \[ans=\sum_iAi-\sum_{i<j}{Ai∩Aj}+\sum_{i<j<k}{Ai∩Aj∩Ak}+.. ...
- Unity3D教程:换装方法
http://www.manew.com/4136.html 游戏内的角色,能够像纸娃娃换装那样子让玩家可以为自己的角色改变外观,一直是相当受欢迎的功能:一般而言,我们建好的 3D 模型,如果要将其中 ...
- 聊聊Java并发面试问题之公平锁与非公平锁是啥?
一.什么是非公平锁? 先来聊聊非公平锁是啥,现在大家先回过头来看下面这张图. 如上图,现在线程1加了锁,然后线程2尝试加锁,失败后进入了等待队列,处于阻塞中.然后线程1释放了锁,准备来唤醒线程2重新尝 ...
- IT兄弟连 JavaWeb教程 Servlet线程安全问题
在Internet中,一个Web应用可能被来自西面八方的客户并发访问(即同时访问),而且有可能这些客户并发访问的是Web应用中的同一个Servlet,Servlet容器为了保证能同时相应多个客户端要求 ...