众所周知,当我们在 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)并且绝对不会造成内存泄漏。
1.要删除事件监听器,您需要将函数作为参考传递,因此addEventListener('click',function(){alert('something')},false)
不起作用。
2.我阅读了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 的下载管理器。下载地址的输入框:
1.xhr to get the fileinfo (size,name,acceptranges,mime)
2.store info in localstorage and cached array
2.create visual dom elements to show progress (event:progress,click,mouseover..)
3.xhr request a chunk 0-1000(event:load)
4.onprogress display progress data (event:progress,error)
5.request filesystem(event:ok,error)
6.readfile/check file (event:ok,error)
7.request filewriter (event:ok,error)
8.append to file (events=ok,error)
9.on ok start again from 3. until file is finished
10.when finished i delete all the **references / events / extra info**
//this to help the garbage collector.
11.change the dom contents.
每个文件每秒都有很多事件。
这 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 不起作用。
这行得通......但我需要很多检查,如果并执行多个功能。
(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)
绑定:
(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)