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

2023-12-24

众所周知,当我们在 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获取文件信息(大小、名称、接受范围、mime)
  2. 将信息存储在本地存储和缓存数组中
  3. 创建可视 DOM 元素来显示进度(事件:进度、单击、鼠标悬停...)
  4. xhr请求一个块 0-1000(事件:加载)
  5. onprogress 显示进度数据(事件:进度,错误)
  6. 请求文件系统(事件:正常,错误)
  7. 读取文件/检查文件(事件:正常,错误)
  8. 请求文件编写器(事件:正常,错误)
  9. 附加到文件(事件=正常,错误)
  10. 就ok了,从3开始重新开始,直到文件完成
  11. 完成后我删除所有参考资料/事件/额外信息//这可以帮助垃圾收集器。
  12. 更改 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)

更好的解决方案是让你的“班级”实施事件监听器界面。

您可以通过添加一个来做到这一点handleEvent方法MyClass.prototype。这允许您将对象直接传递给.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(),就像从元素中正常执行一样,但再次传递对象而不是处理程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将事件函数绑定到类,但使用removeEventListener并删除引用,从而使垃圾收集器能够正常工作 的相关文章

  • 如何测试 javascript 闭包内的函数

    这似乎是不可能的 也可能是 但我正在尝试更多的 TDD 但我总是在闭包方面碰壁 假设我有以下内容 function createSomething init function privateMethod param return init
  • Android 设备上的 PhoneGap 蓝牙插件

    我一直在尝试让 PhoneGap 工作的蓝牙插件 但我似乎不知道哪里出了问题 首先 我的测试设备是 Galaxy S3 GT 19305T 应用程序是使用PhoneGap CLI http docs phonegap com en 3 0
  • Web 串行 API - 未捕获(承诺中)DOMException:无法打开串行端口/所需成员 baudRate 未定义

    下面的代码可以在我的 Xubuntu 机器上运行 但现在我在 Kubuntu 上 它不再工作了 它不会打开端口 Arduino IDE 工作正常 可以向开发板写入代码 并且我可以在 Chrome 中选择设备 Arduino Uno 但当我尝
  • 如何重定向到 instagram://user?username={username}

    我的 html 页面上有这个链接 可以在特定用户上打开 Instagram 应用程序 a href Link to Instagram Profile a 我一直在寻找自动运行 url instagram user username USE
  • 如何监听 jQuery AJAX 请求?

    以下两种实现 ajaxRequest 1 2 的方法应该是等效的 话说回来 为什么验证回调已执行的单元测试 3 在 1 中成功而在 2 中失败 我应该如何重写测试 3 来监视 2 中的成功回调 如果我尝试stub jQuery ajax使用
  • Javascript正则表达式用于字母字符和空格? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我需要一个
  • Node.js:如何在检索数据(块)时关闭响应/请求

    我正在用 node js 构建一个应用程序 它加载多个页面并分析内容 因为 node js 发送块 所以我可以分析这些块 如果一个块包含例如索引 nofollow 我想关闭该连接并继续其余部分 var host example com to
  • Jquery/Javascript 上传和下载文件,无需后端

    是否可以在没有后端服务器的情况下在 JavaScript 函数中下载和上传文件 我需要导出和导入由 JavaScript 函数生成的 XML 我想创建按钮 保存 xml 来保存文件 但我不知道是否可行 另一方面 我希望将 XML 文件直接上
  • 表单计算器脚本基本价格未加载 OnLoad

    我的表单中有一个计算器来计算我的下拉选项选择 function select calculate on change calc input type checkbox calculate on click calc function cal
  • Javascript 数组到 VBScript

    我有一个使用 Javascript 构建的对象数组 我需要使用 VBScript 读取它 如下例所示 我找不到在 VbScript 代码中循环遍历数组的方法myArray object 这个例子是我的问题的简化 我无法更改页面的默认语言 这
  • 如何使用tampermonkey模拟react应用程序中的点击?

    我正在尝试使用 Tampermonkey 脚本模拟对 React 元素的点击 不幸的是 由于 React 有自己的影子 DOM 所以天真的方法使用document querySelector 不工作 我遇到了一些需要修改 React 组件本
  • Laravel 中只向登录用户显示按钮

    如果我以 John 身份登录 如何才能只显示 John 的红色按钮而不显示 Susan 的红色按钮 测试系统环境 Win10 Laravel5 4 Mysql5 7 19 table class table table responsive
  • HTML 离线应用程序缓存,列出下载的文件

    作为我正在构建的离线 Web 应用程序的加载屏幕的一部分 使用缓存清单 http developer apple com library safari documentation iPhone Conceptual SafariJSData
  • FireFox 中的自动滚动

    我的应用程序是实时聊天 我有一个 Div 来包装消息 每条消息都是一个 div 所以 在几条消息之后 我的 DOM 看起来像这样 div div Message number two div div div div
  • 在 vue.js 中访问数组对象属性

    给定以下数组vue js packageMaps Object packageMap 0 Object Id 16 PackageType flag list ProductCode F BannerBase packageMap 1 Ob
  • 条件在反应本机生产中失败,但在开发中有效

    我创建了一个反应本机应用程序 我需要通过它进行比较 如果属实 就会执行死刑 问题是 该条件适用于 React Native 开发模式 而不适用于 React Native 生产版本 我使用 firebase 作为数据库 也使用 redux
  • Safari 支持 JavaScript window.onerror 吗?

    我有一个附加到 window onerror 的函数 window onerror function errorMsg url line window alert asdf 这在 firefox chrome 和 IE 中工作正常 但在 s
  • 如何更改此 jquery 插件的时区/时间戳?

    我正在使用这个名为 timeago 的插件 在这里找到 timeago yarp com 它工作得很好 只是它在似乎不同的时区运行 我住在美国东部 费城时区 当我将准确的 EST 时间放入 timeago 插件时 比如 2011 05 28
  • 如何在 pg-promise 中设置模式

    我正在搜索的文档pg 承诺 https github com vitaly t pg promise特别是在创建客户端时 但我无法找到设置连接中使用的默认架构的选项 它始终使用public架构 我该如何设置 通常 为数据库或角色设置默认架构
  • 使用 Ajax 请求作为源数据的 Jquery 自动完成搜索

    我想做的事 我想使用 jquery 自动完成函数创建一个输入文本字段 该函数从跨域curl 请求获取源数据 结果应该与此示例完全相同 CSS 在这里并不重要 http abload de img jquerydblf5 png http a

随机推荐