ご存知のように、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.ivar 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
}
上記のこの例でわかるように、私はすべてにアクセスでき、参照は単なる小さな文字列です...
getElementById()
毎回呼び出す必要がないように、ロード時に dom 参照を定義するため、dom を保存します。
外部から xhr.abort() を呼び出せるようにしたいので、XHR のようなイベントをクラスに保存します。また、removeEventListener を呼び出すこともできます。
メモリへの影響を最小限に抑える必要がありますが、反対側では、すべてのイベントと参照を削除してガベージコレクターを「手動で」制御するために、複数の同時イベントを持つ多くの要素を制御する必要があります。
問題が見た目よりも大きいことを理解していることを確認するために...: これは chrome のダウンロード マネージャーです。ダウンロード URL の入力フィールド:
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=これは機能しません。
これは機能します...しかし、私はたくさんのチェックが必要です.swich 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)
練る :
(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)