IE6/7的事件注册,闭包导致内存泄露问题
IE6/7由于使用引用计数,容易产生内存泄露问题。
事件注册,由于容易使用闭包,导致问题产生:
//循环引用:element的事件函数(闭包)可以指向element。 var addListener = function (element, eventName, handler) { element.attachEvent('on' + eventName, function () { handler.call(element, window.event); }); };
一种处理的方式,就是先把事件函数存起来,在页面离开的时候,进行事件的移除,解除循环引用。
var register = []; function createObj(el,fn,name){ return { el: el, fn: function(e){ fn.call(el,e||window.event); }, eventName: name }; } var addListener = function (element, eventName, handler) { var obj = createObj(element,handler,eventName); element.attachEvent('on' + eventName,obj.fn); register.push(obj); }; function cleanupListeners(){ for(var i=0; i < register.length;i++){ var item = register[i]; item.el.detachEvent('on' + item.eventName,item.fn); register[i] = null; } } window.attachEvent('onunload', cleanupListeners);
如果嫌这种方式可能带来一些麻烦,譬如onunload事件的影响,我们考虑,重新设计事件注册函数,一开始,就避开闭包的产生:(这里的代码,只是作为思路演示之用。)
ar register = [], fns = {}, els = {}; var getUid = (function (){ var id = 0; return function(){ return "_uid_" + id++; } })(); function setElUid(el){ el.uid = getUid(); return el; } function getElByUid(uid){ return els[uid]; } function createFn(uid,fn){ fns[uid] = function(e){ fn.call(getElByUid(uid),e||window.event); }; return fns[uid]; } function createObj(el,fn,name){ setElUid(el); return { el: el, fn: createFn(el.uid,fn), name: name }; } var addListener = function (element, eventName, handler) { var obj = createObj(element,handler,eventName); element.attachEvent('on' + eventName,obj.fn); register.push(obj); };
相关推荐
yuwinter 2020-10-14
归去来兮 2020-09-18
Ericbig 2020-07-19
chaigang 2020-06-27
yogoma 2020-06-14
Andrewjdw 2020-05-27
jokerdby 2020-05-19
Kingonion 2020-04-23
ELEMENTS爱乐冬雨 2020-04-21
sunlizhen 2020-04-17
LczPtr 2020-04-14
Livis的开发之路 2020-03-11
Airuio 2020-03-06
Livis的开发之路 2020-02-28