其实不知道怎么起这篇blog的题目了 其实只要涉及的内容是内存泄漏的问题,也有内存管理的一些知识,把学习的过程拿来分享
垃圾回收机制
js具有自动的垃圾收集机制,它会找出那些不在继续使用的变量然后释放其内存,垃圾收集器会按照固定的时间间隔周期性的执行这一操作
我们通过下面的例子来理解垃圾收集器的执行过程
<div id="test">sss</div> <script type="text/javascript"> function test() { this.elem = document.getElementById("test"); } var a = new test(); document.body.innerHTML = ""; console.log(a.elem);//<div id="test">sss</div>
console.log(document.getElementById("test"));//null a = new test(); console.log(a.elem);//null </script>
在上面的例子中,我们定义了一个构造函数,它返回的对象中有elem属性指向页面中id为test的元素,我们创建了一个变量a指向构造函数返回的对象,然后在父元素中删除这个id为test的元素,但是我们通过a.elem属相仍然能获取到这个id为test的div 但是我们通过正常的document.getElementById("test")已经无法获取到这个元素了,此时这个div元素只存在内存中,是因为这个div被这个elem引用着,所以它不会被垃圾回收器回收,仍然存在内存中.当我们重新将变量a指向另一个返回的引用值的时候,此时不存在对这个div的引用了,这段内存就会被回收,第二次输出a.elem输出为null是因为页面中不存在这个id为test的元素
闭包经常会导致环装的引用
<div id="test">sss</div> <script type="text/javascript"> function test() { var div = document.getElementById("test"); div.onclick = function() { console.log(1); } } test();
在上面的例子中 有这样一个函数,它的功能是为页面中id为test的元素绑定click事件,这个click事件(function)绑定后,就存在了js的运行环境(内存中),它引用了一个局部的变量div,这样当这个函数运行完后,这个局部变量div所占据的内存不会被垃圾回收器回收,会存在在内存中,这样就会导致内存的泄漏
仔细理解闭包:
function test() { var a = 100; var b = 200; function say(){ } return say; } var aa = test();
在上面的例子中,我们定义了一个方法,它有两个局部的变量 a b 和一个方法say并且通过return语句返回了这个方法,这就构成了一个闭包.这个时候say存在内存中,它引用的父级作用域的变量也会存在内存中,也就是a b 也同时存在内存中,(js的解释器无法优化的知道say方法到底使用了父级作用域的哪些变量和方法,所以它将父级作用域的所有变量和方法都保存在内存中,不被垃圾回收器回收),这也造成内存的泄漏
管理内存
系统分配给浏览器的内存是存在一定的限制的,我们必须更好的管理好这些内存才能更好的使我们的网页性能最大化,目标就是尽可能的保存必要的数据,将不必要的数据通过解除引用,设置其为null.这样做的目的是让这个变量脱离当前的执行环境,以便在垃圾回收器下次运行的时候对这个变量的内存进行回收
function test() { var a = 100; var b = 200; function say(){ } var a = null; var b = null; return say; } var aa = test();
上面的例子就将a b脱离的执行环境,在垃圾回收器下次运行的时候,会被回收
参考 JavaScript高级程序设计 memory leaks
2016 5 10 事件处理中的内存问题
为什么添加事件处理程序会增加内存的占用 事件处理程序就是函数,在js中函数均是对象,对象的存在就会占用内存,如何最小化的添加事件处理程序就最大限度的提高了页面的性能 所以出现了事件委托
通过事件冒泡,在父元素处理上通过event.target来进行事件的处理
移除不需要的事件处理程序也能降低内存的占用 但是这种情况有例外的情况
<div> <input type="button" value="test" /> </div>
在上面的例子中,我们为button添加了事件处理程序,当获取外层的div 并且通过innerHTML将这个button移除的时候,可能会存在这个btn 和 事件处理程序还存在页面的情况 也就是这篇blog刚开始的例子,所以当我们要移除元素的时候,可以将他的事件处理程序设置为null(移除事件处理程序)
2016 6 19 贴出一篇园友的blog 讲解的很细致 javascript中对内存的一些了解 在这篇文章中引用了另一篇园友的文章 var a.x = a = {n:2}的这个问题很有意思