众所周知,当我们在 JavaScript 中创建类时,普通函数会返回类对象,但事件会返回事件对象,并且类对象会丢失:
function class(a){
this.name=a;
document.addEventListener('click',this.click,false);
xhr.addEventListener('load',this.xhr,false);
this.normal()
}
class.prototype={
click:function(e){
//e=event,this=theDocument //can't access class
},
xhr:function(e){
//e=event,this=theXHR //can't access class
},
normal:function(e){
//e=null,this=class
}
}
将这些事件绑定到我们的类的最佳方法是什么?
最好的方式我的意思是没有或只是一个很小的参考,以本机方式删除事件的能力(removeEventListener
)并且绝对不会造成内存泄漏。
-
要删除事件侦听器,您需要传递该函数作为引用,因此addEventListener('click',function(){alert('something')},false)
不起作用。
-
我读过类似的参考文献var that=this
内部函数会产生泄漏;真的?
已知方法:
function class(a){
this.name=a;
var that=this;// reference
//simply reference the whole object as a variable.
var bindedClick=this.click.bind(this);//bind the click to the class
//(js 1.85)
//can i use removeEventListener('click',bindedClick,false) later?
//apply && call (js 1.3)
}
因为我不确定是否var that=this
(因为它是整个对象)会产生泄漏,有时我通过将信息保存到数组中来最小化泄漏,并使用 id 作为参考:
var class={};
var id='ID'+Date.now();
class[id].info={here i store all the info i need later text only}
//this will be stored also in a cookie / Localstorage to reuse later.
class[id].dom={here i store the dom references}
class[id].events{here i store the xhr events}//if needed
//this are Temp only
为了获取信息,我只需将 id 添加到事件元素中即可传递:
class[id].events.xhr.id=id;
class[id].events.xhr.onload=class.f
class.prototype.f=function(e){
//this.response,class[this.id]<- access everything.
this.removeEventListener('load',class.f,false);
delete class[this.id].events.xhr;
delete this.id
}
class[id].dom.id=id;
class[id].dom.onclick=class.f2
class.prototype.f2=function(e){
//class[e.target.id],class[this.id]<- access everything.
this.removeEventListener('click',class.f2,false);
delete class[this.id].dom;
delete this.id
}
正如您在上面的示例中看到的,我可以访问所有内容,而引用只是一个小字符串。
我存储 DOM 因为我在加载时定义了 DOM 引用,所以我不必调用getElementById()
每次。
我将像 XHR 这样的事件存储在类中,因为我希望能够调用xhr.abort()
从外面,也可以打电话removeEventListener
.
我需要尽量减少对内存的影响,但另一方面,我需要控制许多具有多个并发事件的元素,通过删除所有事件和引用来“手动”控制垃圾收集器。
为了确保您了解问题比看起来更严重:
它是 Chrome 的下载管理器。下载地址输入框:
-
xhr
获取文件信息(大小、名称、接受范围、mime)
- 将信息存储在本地存储和缓存数组中
- 创建可视 DOM 元素来显示进度(事件:进度、单击、鼠标悬停...)
-
xhr
请求一个块 0-1000(事件:加载)
- onprogress 显示进度数据(事件:进度,错误)
- 请求文件系统(事件:正常,错误)
- 读取文件/检查文件(事件:正常,错误)
- 请求文件编写器(事件:正常,错误)
- 附加到文件(事件=正常,错误)
- 就ok了,从3开始重新开始,直到文件完成
- 完成后我删除所有参考资料/事件/额外信息//这可以帮助垃圾收集器。
- 更改 DOM 内容。
每个文件每秒都有很多事件。
这3个中哪一个是最好的解决方案或者有更好的解决方案吗?
bind();//or call / apply
var that=this; //reference to the whole object
var id=uniqueid; // reference to the object's id
根据答案:
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
var that=this;
var btn=D.createElement('button');
btn.addEventListener('click',this.clc,false);
D.body.appendChild(btn);
}
dl.prototype={
clc:function(e){
console.log(that)
}
}
W.addEventListener('load',init,false);
})(window)
var that=this
不起作用。
这有效;但我需要很多检查,切换 if 并执行多个函数。
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
this.btn=D.createElement('button');
btn.addEventListener('click',this,false);
D.body.appendChild(btn);
}
dl.prototype={
handleEvent:function(e){
e.target.removeEventListener('click',this,false);//does this the work?
return this.clc(e);
},
clc:function(e){
console.log(this,e)
}
}
W.addEventListener('load',init,false);
})(window)
BIND :
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
this.clcB=this.clc.bind(this);
this.btn=D.createElement('button');
this.btn.addEventListener('click',this.clcB,false);
D.body.appendChild(this.btn);
}
dl.prototype={
clc:function(e){
e.target.removeEventListener('click',this.clcB,false);//does this the work?
delete this.clcB;
console.log(this)
}
}
W.addEventListener('load',init,false);
})(window)