4、 复制代码 代码如下: function bindEvent() { var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it"s a empty function } }
闭包非常容易构成循环引用。如果一个构成闭包的函数对象被指定给,比如一个 DOM 节点的事件处理器,而对该节点的引用又被指定给函数对象作用域中的一个活动(或可变)对象,那么就存在一个循环引用。 DOM_Node.onevent -<function_object.[[scope]] -<scope_chain -<Activation_object.nodeRef -<DOM_Node。
形成这样一个循环引用是轻而易举的,而且稍微浏览一下包含类似循环引用代码的网站(通常会出现在网站的每个页面中),就会消耗大量(甚至全部)系统内存。 解决之道,将事件处理函数定义在外部,解除闭包 复制代码 代码如下: function bindEvent() { var obj=document.createElement("XXX"); obj.onclick=onclickHandler; } function onclickHandler(){ //do something }
或者在定义事件处理函数的外部函数中,删除对dom的引用(题外,《JavaScript权威指南》中介绍过,闭包中,作用域中没用的属性可以删除,以减少内存消耗。) 复制代码 代码如下: function bindEvent() { var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it"s a empty function } obj=null; }
5、 复制代码 代码如下: a = {p: {x: 1}}; b = a.p; delete a.p;
执行这段代码之后b.x的值依然是1.由于已经删除的属性引用依然存在,因此在JavaScript的某些实现中,可能因为这种不严谨的代码而造成内存泄露。所以在销毁对象的时候,要遍历属性中属性,依次删除。 6. 自动类型装箱转换 别不相信,下面的代码在ie系列中会导致内存泄露 复制代码 代码如下: var s=”lalala”; alert(s.length);
s本身是一个string而非object,它没有length属性,所以当访问length时,JS引擎会自动创建一个临时String对象封装s,而这个对象一定会泄露。这个bug匪夷所思,所幸解决起来相当容易,记得所有值类型做.运算之前先显式转换一下: 复制代码 代码如下: var s="lalala"; alert(new String(s).length);