前些天在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上基本上也没有什么问题。”
分享到:
相关推荐
【Android手机RSS阅读器html5.zip】是一款专为Android平台设计的RSS阅读应用,它结合了HTML5技术,提供了一种高效、便捷的方式来获取和阅读RSS订阅源中的内容。这款应用充分利用了HTML5的特性,如离线存储、多媒体...
【标题】"RSS Episode Filter: 开始应用"指的是一个针对RSS(Really Simple Syndication) feed的筛选工具,可能是一个JavaScript项目,旨在帮助用户过滤和管理RSS订阅中的特定章节或剧集。RSS是一种标准,用于发布...
在ASP.NET中,可以使用主题和皮肤机制,预先定义好多种样式,根据用户选择动态加载。 总结起来,网站开发中的注册与登录、留言版和RSS订阅模块涉及到了用户认证、数据交互、内容管理等多个方面,而ASP.NET和C#提供...
4. **google_chrome_rss_icon.user.js**:这个脚本可能在Chrome浏览器中添加了一个功能,使得用户可以在支持RSS订阅的网站上快速找到并订阅RSS源。 5. **SmoothScroll.user.js**:这类脚本通常用于平滑滚动页面,...
2. **RSS/Atom订阅**:许多新闻网站提供RSS(简易聚合)或Atom格式的订阅源,新闻阅读器通过解析这些XML文件获取最新的文章标题、摘要和链接。用户可以订阅感兴趣的新闻源,阅读器会自动检查更新并呈现内容。 3. **...
- 在IIS中启用应用程序池的回收机制,避免长时间运行导致的内存泄漏问题。 - 在`web.config`文件中配置错误自定义处理(`<customErrors mode="On" />`),以便更好地处理和报告错误信息。 - 将调试模式设置为关闭(`...
新闻展示部分可能采用了RSS订阅或者API接口的方式,实时获取并更新新闻内容。这需要后端与外部新闻源进行通信,可能涉及到HTTP请求、JSON解析等技术。新闻数据通常存储在数据库中,以便快速检索和展示。 系统开发中...
后台可能采用RSS订阅或爬虫技术收集信息,再通过内容管理系统(CMS)进行编辑和发布,同时推送通知至用户端,这涉及到了推送服务如极光推送或信鸽推送。 5. **微信小程序开发**:作为一款微信小程序,其开发遵循...
与XML格式的RSS或Atom相比,JSON Feed采用JSON(JavaScript Object Notation)作为其数据载体,JSON是一种轻量级的数据交换语言,易于人类阅读和编写,同时也易于机器解析和生成。由于其简洁的语法,JSON Feed在开发...
4. **API接口**:为了获取和更新实时资讯,程序可能需要对接第三方API,例如RSS订阅服务、新闻聚合API或社交媒体API。 5. **用户体验(UX)和响应式设计**:确保程序在不同设备上(如手机、平板电脑和桌面电脑)都...