精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-08-31
最后修改:2009-09-01
以前写过一点关于动态加载js的东东,而上次自己在看到一篇老外的文章后再次记录了点东西,不过昨天中午看到另一篇老外的博客的时候发现说会引起“内存泄露”!自己感到非常惊讶,现在几乎都是这样动态加载外部的js文件啊(包括流行的一些Javascript库,比如YUI get()),可能方式不一样,原理却都差不多啊 原文在这里:“http://neil.fraser.name/news/2009/07/27/”,赶紧继续往下看,可惜自己英语确实不是很好,很多单词不认识,汗
大意是:利用Script标签可以跨域加载并运行一段JavaScript脚本:
script = document.createElement('script'); script.src = 'http://example.com/cgi-bin/jsonp?q=What+is+the+meaning+of+life%3F'; script.id = 'JSONP'; script.type = 'text/javascript'; script.charset = 'utf-8'; var head = document.getElementsByTagName('head')[0]; head.appendChild(script); 通过url传递的是Javascript数据格式,即json。如果我们一次加载的数据量太多,可以分开来加载。这种方式如果是运行一两次,没有任何问题,但是当重复很多次后,head的头部会“充斥”很多script标签,所以我们需要删除旧的标签:
var script; while (script = document.getElementById('JSONP')) { script.parentNode.removeChild(script); } 作者在这里指出了一个问题:这种方式可以成功的从dom树中删除script标签,可是,问题在于当你清除这些script标签的时候,当今的几乎所有浏览器仅仅是移除该标签结点,而没有对节点内的资源进行垃圾回收。所以,作者在这里移除Script标签后,为了释放脚本资源,还手动清除script标签结点的内容:
var script; while (script = document.getElementById('JSONP')) { script.parentNode.removeChild(script); for (var prop in script) { delete script[prop]; } } 无demo无真相,所以,在此处,我还是希望用代码来验证一下作者的观点,按照作者的思路,我写了两页页面,代码如下: Code1:
var script; while (script = document.getElementById('JSONP')) { alert(script) script.parentNode.removeChild(script); for (var prop in script) { delete script[prop]; } alert(script.id); alert(script["src"]); } Code2:
var script; while (script = document.getElementById('JSONP')) { script.parentNode.removeChild(script); alert(script.id); alert(script["src"]); } 两个页面的结果是一样,都是先后弹出“JSONP”、“little.js”,而且,测试一下delete运算的返回值,结果为“true”,表示删除成功(注:对象属性不存在时也返回true。但此处很显然属性时存在的。故能根据返回值判断删除是否成功)。这个我就搞不明白了,而更有意思的是:测试页面1(即代码1)在安装了Leak Monitor的firefox下面竟然还提示“内存泄露”的错误!
IE下面,测试页面1报错,原因是delete导致了错误! 我不知道为什么会出现这样的结果,所以我对作者的观点至今抱有怀疑的态度,希望在这里得到大牛的解答~ 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-08-31
最后修改:2009-08-31
标签内的代码已经被浏览器解释执行了,清楚标签并不能清楚已经执行所产生的对象,
要想彻底删除只能手动对标签执行产生的对象进行清除, 可以看一下: http://yiminghe.iteye.com/blog/419200 |
|
返回顶楼 | |
发表时间:2009-09-03
Neil Fraser说的并非标签内的代码会导致内存泄漏,而是这个script标签
ie下不允许delete原生对象的属性,他给出的解决办法是,不删除script,仅使用一个script. |
|
返回顶楼 | |
发表时间:2009-09-03
最后修改:2009-09-03
我觉得那篇老外文章里唯一可取的是关于ie允许复用同一个script标签的那段…………
TUI.getJSON = (function($, TUI){ var jsonp = {}; return function(url, fn, op){ var domain = url.match(/http:\/\/(.+?)\//); if (!domain || domain[1] === window.location.host) { $.getJSON(url, fn); return true; } op = $.extend({ charset: "gbk", callback: "jsonp" + +new Date() }, op || {}); var random = op.random ? ( "&" + op.random + "=" + +new Date() ) : ""; url = [url, /\?/.test(url) ? "&" : "?", "jsoncallback=", op.callback, random].join(""); if (fn) TUI.namespace(op.callback, fn); var s, h; if (op.repeat && $.browser.msie) { //在ie里,对多次请求使用同一个script,避免内存泄漏 var sid = jsonp[domain[1]]; if (!sid) { sid = jsonp[domain[1]] = "tui_jsonp" + +new Date(); s = document.createElement("script"); s.id = sid; s.type = "text/javascript"; s.charset = op.charset; s.src = url; h = document.getElementsByTagName("head")[0]; h.appendChild(s); } else { s = document.getElementById(sid); s.charset = op.charset; s.src = url; } } else { s = document.createElement("script"); s.type = "text/javascript"; s.charset = op.charset; s.src = url; h = document.getElementsByTagName("head")[0]; var done = false; s.onload = s.onreadystatechange = function(){ if ( !done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") ) { done = true; //防止ie内存泄漏 s.onload = s.onreadystatechange = null; h.removeChild(s); //减少非ie浏览器的内存泄漏 //if (op.repeat && !$.browser.msie) { //for (var prop in s) //delete s[prop]; //} } }; h.appendChild(s); } }; })(jQuery, TUI); |
|
返回顶楼 | |
发表时间:2009-09-03
lixinlixin2008 写道
Neil Fraser说的并非标签内的代码会导致内存泄漏,而是这个script标签
ie下不允许delete原生对象的属性,他给出的解决办法是,不删除script,仅使用一个script. 建议写页面去测试一下,个人感觉作者的观点不一定就是正确的,我用delete删除发现还是有泄漏的问题
|
|
返回顶楼 | |
发表时间:2009-09-03
dexter_yy 写道
我觉得那篇老外文章里唯一可取的是关于ie允许复用同一个script标签的那段…………
TUI.getJSON = (function($, TUI){ var jsonp = {}; return function(url, fn, op){ var domain = url.match(/http:\/\/(.+?)\//); if (!domain || domain[1] === window.location.host) { $.getJSON(url, fn); return true; } op = $.extend({ charset: "gbk", callback: "jsonp" + +new Date() }, op || {}); var random = op.random ? ( "&" + op.random + "=" + +new Date() ) : ""; url = [url, /\?/.test(url) ? "&" : "?", "jsoncallback=", op.callback, random].join(""); if (fn) TUI.namespace(op.callback, fn); var s, h; if (op.repeat && $.browser.msie) { //在ie里,对多次请求使用同一个script,避免内存泄漏 var sid = jsonp[domain[1]]; if (!sid) { sid = jsonp[domain[1]] = "tui_jsonp" + +new Date(); s = document.createElement("script"); s.id = sid; s.type = "text/javascript"; s.charset = op.charset; s.src = url; h = document.getElementsByTagName("head")[0]; h.appendChild(s); } else { s = document.getElementById(sid); s.charset = op.charset; s.src = url; } } else { s = document.createElement("script"); s.type = "text/javascript"; s.charset = op.charset; s.src = url; h = document.getElementsByTagName("head")[0]; var done = false; s.onload = s.onreadystatechange = function(){ if ( !done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") ) { done = true; //防止ie内存泄漏 s.onload = s.onreadystatechange = null; h.removeChild(s); //减少非ie浏览器的内存泄漏 //if (op.repeat && !$.browser.msie) { //for (var prop in s) //delete s[prop]; //} } }; h.appendChild(s); } }; })(jQuery, TUI); 用到了jQuery框架,呵呵,代码写的不错 不过IE确实很让人抓狂了 |
|
返回顶楼 | |
发表时间:2009-09-06
clone168 写道
lixinlixin2008 写道
Neil Fraser说的并非标签内的代码会导致内存泄漏,而是这个script标签
ie下不允许delete原生对象的属性,他给出的解决办法是,不删除script,仅使用一个script. 建议写页面去测试一下,个人感觉作者的观点不一定就是正确的,我用delete删除发现还是有泄漏的问题
前段时间做一个项目是: http://imgdb.mapenjoy.com 会很频繁的请求json,我测试拖动地图一段时间后内存会有轻微的上涨...也不知道是不是script引起的内存泄漏...因为程序比较复杂, 不过看起来即使泄漏,泄漏的也很轻微...
有机会测试测试吧...有空可否把你的测试代码发给俺呢 |
|
返回顶楼 | |
发表时间:2009-09-07
最后修改:2009-09-07
lixinlixin2008 写道
clone168 写道
lixinlixin2008 写道
Neil Fraser说的并非标签内的代码会导致内存泄漏,而是这个script标签
ie下不允许delete原生对象的属性,他给出的解决办法是,不删除script,仅使用一个script. 建议写页面去测试一下,个人感觉作者的观点不一定就是正确的,我用delete删除发现还是有泄漏的问题
前段时间做一个项目是: http://imgdb.mapenjoy.com 会很频繁的请求json,我测试拖动地图一段时间后内存会有轻微的上涨...也不知道是不是script引起的内存泄漏...因为程序比较复杂, 不过看起来即使泄漏,泄漏的也很轻微...
有机会测试测试吧...有空可否把你的测试代码发给俺呢 我的测试页面以及测试结论你可以到这里看看:http://hi.baidu.com/hulk168/blog/item/3e55488f07ddf8f3513d92f7.html |
|
返回顶楼 | |
浏览 8786 次