gpt4 book ai didi

javascript - 将事件函数绑定(bind)到类,但使用 removeEventListener 并删除其引用,从而使垃圾收集器能够正常工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:34:42 26 4
gpt4 key购买 nike

众所周知,当我们在 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
}
}

将这些事件绑定(bind)到我们的类的最佳方法是什么?

最好的方式我的意思是没有或只是一个很小的引用,能够以 native 方式删除事件(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 不起作用。

这行得通...但是我需要大量的检查,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)

绑定(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)

最佳答案

更好的解决方案是让您的“类”实现EventListener 接口(interface)。

您可以通过向 MyClass.prototype 添加一个 handleEvent 方法来实现。这允许您将对象直接传递给 .addEventListener() 而不是传递处理程序。

当事件发生时,handleEvent() 方法将被调用,您的对象作为this 值。这使您可以访问对象的所有属性/方法。

function MyClass(a) {
this.name = a;

// pass the object instead of a function
document.addEventListener('click', this, false);
xhr.addEventListener('load', this, false); // where did `xhr` come from?

this.normal()
}

MyClass.prototype = {

// Implement the interface
handleEvent: function(e) {
// `this` is your object
// verify that there's a handler for the event type, and invoke it
return this[e.type] && this[e.type](e);
},

click: function (e) {
// `this` is your object
},
load: function (e) {
// `this` is your object
},
normal: function (e) {
// `this` is your object
}
}

请注意,我将您的 xhr 方法的名称更改为 load。这使得根据事件类型调用正确的方法变得更加容易。

然后当需要调用 .removeEventListener() 时,就像元素中的正常操作一样,但再次传递对象而不是处理程序。

关于javascript - 将事件函数绑定(bind)到类,但使用 removeEventListener 并删除其引用,从而使垃圾收集器能够正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18276516/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com