;(function (){ var $el = {tag: 'div', dom: null} $el.dom = document.getElementById('test') // JS Engine Object references to DOM Element $el.dom.attachEvent('click', onclick) // DOM Element references to JS Engine Object // 此时还没形成circular references  function onclick(){} // onclick的方法体内隐式引用$el及$el内的dom属性,因此形成了circular refereneces // function onclick(){ return eval('$el && true || false') } 返回true }()) 

Non-Leak Memory

  ;(function (){ var $el = {tag: 'div', dom: null} $el.dom = document.getElementById('test') // JS Engine Object references to DOM Element $el.dom.attachEvent('click', onclick) // DOM Element references to JS Engine Object // 此时还没形成circular references }()) function onclick(){} // onclick方法体内没有引用$el 

3.3. Cross-page Leaks(当前页面内存泄漏)

由于节点建立联系时会寻找scope,若没有则创建temporary scope,若有则抛弃原有的temporary scope采用已有的scope。

怎么用JS理解IE的内存泄露

Leak Memory

   function LeakMemory() { var hostElement = document.getElementById("hostElement"); // Do it a lot, look at Task Manager for memory response  for (i = 0 ; i < 5000 ; i ++ ) { var parentDiv = document.createElement(""); var childDiv = document.createElement(""); // This will leak a temporary object parentDiv.appendChild(childDiv); hostElement.appendChild(parentDiv); hostElement.removeChild(parentDiv); parentDiv.removeChild(childDiv); parentDiv = null ; childDiv = null ; } hostElement = null ; }     Memory Leaking Insert    

当childDiv与parentDiv建立连接时,为让childDiv能获取parentDiv的信息,IE会创建temporary scope。而当将parentDiv添加到DOM tree中时,则childDiv和parentDiv均继承document的scope,而temporary scope却不会被GC释放,而要等待浏览器刷新页面才能清理。

Non-Leak Memory

   function CleanMemory() { var hostElement = document.getElementById("hostElement"); // Do it a lot, look at Task Manager for memory response  for (i = 0 ; i < 5000 ; i ++ ) { var parentDiv = document.createElement(""); var childDiv = document.createElement(""); // Changing the order is important, this won’t leak hostElement.appendChild(parentDiv); parentDiv.appendChild(childDiv); hostElement.removeChild(parentDiv); parentDiv.removeChild(childDiv); parentDiv = null ; childDiv = null ; } hostElement = null ; }     Clean Insert    

一直使用document scope,不会创建temporary scope

3.4. Pseduo-Leaks

连续创建多个JS Engine Object,而GC未能及时释放内存,其实根本就不是内存泄漏

var tmpStr
for(var i = 0; i < 100000; ++i)
tmpStr = "test"

四、当前页面泄漏的示例

4.1. DOM Hyperspace引起的DOM Element引用孤岛

DOM Hyperspace由PPK发现,在IE下通过removeChild或removeNode从父节点(无论是否已加入DOM Tree)中移除节点后,会创建一个新的#documentFragment,并且被移除的节点的parentNode为 该#documentFragment,而该#documentFragment.firstChild为被移除的节点,因此存在DOM Element间的circular reference导致无法释放,只有刷新页面后才会释放资源。

Leak Memory

var div = document.createElement('div')
document.body.appendChild(div)
div.parentNode.removeChild(div)

alert(div.parentNode) // IE8下为[Object object],Chrome等浏览器为null

Non-Leak Memory

function rm(el){ if (!+'\v1'){ var d = document.createElement('div') d.appendChild(el) d.innerHTML = '' } else{ el.parentNode.removeChild(el) } }  var div = document.createElement('div') document.body.appendChild(div) rm(div)  alert(div.parentNode) // IE8下为null

4.2. 释放Iframe没那么简单

iframe所占的资源有两部分:iframe元素所占的内存空间 和 iframe内页面所占的内存空间。

内存空间释放步骤:

1. 释放 iframe内页面所占的内存空间

通过设置src=''或src='about:blank'来释放内部页面的资源

2. 释放 iframe元素所占的内存空间

通过removeChild、removeNode等方法释放iframe元素的内存空间

ligerTab1.2.1的清除方式

var iframe = ...
iframe.src = 'about:blank'
iframe.contentWindow.document.write('')
CollectGarbage && CollectGarbage()
iframe.parentNode.removeChild(iframe)

五、IE8下连续修改IMG的src居然耗尽内存?

由于IE8会对非原始尺寸的图片进行抗锯齿平滑处理,从而消耗更多的CPU和内存资源。当图片大小和尺寸到一定时,则会出现挂死的情况。(IE6、7没有抗锯齿平滑处理,而IE9则移除该功能)

而这种情况当然就不属于Memory Leak啦!

题外话:

众所周知IMG是replaced element,其width和height属性缺省值又外部资源决定,而我们通过CSS设置的width和height属性均是对缺省值的二次加工。

假设图片原始尺寸为width:200px/height:400px,现在通过CSS设置width:100px,那么图片将按等比例缩放为 width:100px/height:200px;但通过CSS设置width:100px/height:100px时,那么图片则不是按等比例缩放 了。

六、监控工具 

监控方式多种多样,这里大概分为两类:

1. 当前页面泄漏:Windows的任务管理器、Chrome->dev tools->Profiles->Take Heap Snapshot/Record Heap Allocations等等

2. 跨页面泄漏:sIEve

怎么用JS理解IE的内存泄露

操作步骤:

1. 在Address输入框输入网址,点击Go (浏览网页)

2. 执行测试用例

3. 点击about:blank按钮(跳转到空白页)

4. 查看#leaks列下是否有增长,有则表示出现跨页面的内存泄漏

感谢各位的阅读,以上就是“怎么用JS理解IE的内存泄露”的内容了,经过本文的学习后,相信大家对怎么用JS理解IE的内存泄露这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!


分享文章:怎么用JS理解IE的内存泄露
文章路径:http://tjjierui.cn/article/pedpgi.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP