前些天在javaeye上发了一个帖子,“动态加载Javascript会导致内存泄露?”,自己当时被老外的那篇文章搞的比较困惑,网上也请教了一些高人,这里要非常感谢那些帮助我的人,工作非常繁忙的时候还愿意给我讲解他们对问题的看法,真的让我很感动!
这里再介绍一个比较好用的工具:Drip/sIEve,感谢jindw为我推荐这个工具,Drip和sIEve的作者应该是同一个人,连open souce上的项目都是在一起的。不过,平时我们主要使用sIEve就可以了,sIEve的功能比Drip强大一些,sIEve 是一个帮助我们查看ie浏览器(他本身基于操作系统安装的ie内核)内存的使用和内存泄露问题的。具体使用很简单,这里再提供一个链接给大家:http://home.orange.nl/jsrosman/,大家下载下来后就可以使用了。
Firefox下面也有一个检查内存泄露的工具,不过我用过,感觉有时候很让人抓狂,大家有兴趣的不妨也试试。PuterJam为我们总结了一篇“javascript 内存泄露工具使用”,推荐去看看。
来看我做的测试,代码1:
<body>
<script type="text/javascript">
script = document.createElement('script');
script.src = 'little.js';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
</script>
测试页面2
<script type="text/javascript">
var script = document.getElementById('JSONP');
script.parentNode.removeChild(script);
</script>
</body>
在sIEve的结果是:
可以看到,id=JSONP的节点是孤立状态,而没有被回收 (还有一个孤立节点 大家不用管) ,为了解决这个办法,从EXTjs里面的代码得到灵感:
我把页面代码修改成:
<body>
<script type="text/javascript">
script = document.createElement('script');
script.src = 'little.js';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
var body = document.getElementsByTagName('body')[0];
body.appendChild(script);
</script>
测试页面2
<script type="text/javascript">
var script = document.getElementById('JSONP');
var d = document.createElement('div');
d.appendChild(script);
d.innerHTML = '';
</script>
</body>
可惜的是竟然还是存在没被回收的节点,囧!:
这里我暂时还不知道是什么原因,没仔细研究下去,如果是div的话,用这种方式是可以把节点回收的。
克军大牛跟我讲,“再加一行script = null;确实jsonp不能滥用,…,一般解决dom的循环reference就是null掉”,于是我把最后的script对象null掉,发现果然节点不存在了!
Code:
<body>
<script type="text/javascript">
script = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
script.src = 'little.js';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
</script>
测试页面2
<script type="text/javascript">
var script = document.getElementById('JSONP');
script.parentNode.removeChild(script);
script = null;
</script>
</body>
结果图:
看来还是不能想什么奇淫技巧,老老实实把最后的对象引用null掉
ranklau那天抽出时间跟我讲:“…如果用htmlelement,remove后会泄露。用fragment,fragment不用append到DOM上,不会有泄露。一个节点append到dom上,你再移除它就会有泄露的。所以才会出现象ext的trash机制…”,ranklau一看就是高手,我也是陋闻了,这些结论竟然都不知道!不过ranklau也是技术人员一贯的严谨作风,自己没去做测试,所以希望我能去做测试验证这些观点。今天上网找到了这方面的一个帖子,发现“这是IE的一个特点:document fragment不append到document的dom里面的时候,也可以拥有自己的脚本运行空间,可以用script标签发起请求。这样用document fragment就可以比iframe使用更少的客户端资源来完成操作。”好!做测试:
<body>
<script type="text/javascript">
var df = document.createDocumentFragment();
script = document.createElement('script');
script.src = 'little.js';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
df.appendChild(script);
</script>
测试页面2
<script type="text/javascript">
var script = document.getElementById('JSONP');
alert(script);
</script>
</body>
测试结果:
id=JSONP的节点至始至终没有append到页面的dom树上来,是一个孤立的点,但是,null掉后也就被回收了,所以,这种方式也不错!
最后,我却怀疑这个documentFragment会引起内存泄漏,因为浏览器要为这个新节点产生一个新的脚本scope,所以肯定会消耗额外的内存,至于到底是不是这样,还是测试:
Code:
<body>
<script type="text/javascript">
for(var i=0;i<100;i++){
var dom = document.createDocumentFragment();
script = document.createElement('script');
script.src = 'little.js';
script.id = 'JSONP';
script.type = 'text/javascript';
script.charset = 'utf-8';
dom.appendChild(script);
dom.removeChild(script);
script=null;
}
</script>
</body>
如图,发现,还是存在额外的内存消耗
最后,看网上有人说“IE8beta版本不支持documentFragment拥有独立的运行空间,正式版又解决了这个问题”,这个我不确定,因为我至今没装IE8,大家有兴趣可以去测试下,不过我觉得比较稳妥的方式还是最好别用documentFragment。
转自:http://04js.cn/content.asp?id=1613
今天自己再次做了一些测试,和上次不一样,这次集中在IE上面(上次在firefox测试比较多),这几天的请教让我明白:IE与firefox、chrome的解析机制是不一样的,“对于需要频繁动态加载的script(比如跨域的jsonp接口),可以对ie做一下专门的优化,因为ie里Dom解析机制是c++写的,好像属于windows网络堆栈的那个部分,跟Javascript引擎的垃圾回收机制完全不同,内存泄漏问题比较明显……”,“firefox的内存GC机制比IE强悍,不必作为重点考虑对象。只要ie的问题能处理好,firefox上基本上也没有什么问题。”
分享到:
相关推荐
一个js文件,实现动态加载js文件。在用extjs时,为了避免一次全部加载js文件而写的。
【JavaScript】vue动态加载JavaScript 高级JavaScript组件 【实例简介】vue动态加载JavaScript 【JavaScript】vue动态加载JavaScript 高级JavaScript组件
asp.net动态加载JavaScript树
利用Script标签可以跨域加载并运行一段JavaScript脚本, 但Neil Fraser先前已指出,脚本运行后资源并没被释放,即使是Script标签移除后。
实现JavaScript 动态加载事件
一篇文章弄懂javascript内存泄漏 在了解什么是内存泄漏之前, 我们应该要对内存是什么有个概念, 随机存取存储器(英语:Random Access Memory,缩写:RAM)是与 CPU 直接交换数据的内部存储器。它可以随时读写, ...
Javascript内存泄露
javascript、css动态加载工具
vue内存泄露详解 什么是内存泄露?... 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造 成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
javascript 解析 rss 实例 订阅 xml
javascript内存泄露问题的解析 javascript内存泄露问题的解析javascript内存泄露问题的解析
动态加载JavaScript文件的两种方法_.docx
这是动态加载外部JS文件,很不错的例子哦!
vue动态加载JavaScript:动态的创建Script元素,然后通过更改它的 src 属性来加载脚本,脚本文件加载完成后,在脚本加载完成生效后才能执行回调函数。
这篇文章主要为大家详细介绍了动态加载JavaScript文件的两种方法,感兴趣的小伙伴们可以参考一下 第一种便是利用ajax方式,把script文件代码从背景加载到前台,而后对加载到的内容经过eval()实施代码。第二...
使用RSS订阅喜欢的 bilibili up主和番剧
第一篇 javascript控件开发之动态加载
介绍有关JavaScript_内存机制,以及避免内存泄露!
JavaScript中的内存泄漏检测方法研究.pdf