将事件函数绑定到类,但使用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并删除引用,从而使垃圾收集器能够正常工作 的相关文章

  • 如何在 React JS 中根据键创建动态表?

    我正在尝试在 React JS 中创建一个动态表组件 该组件当前只有一个静态标头 其中包括最常见的结果键 有些结果还包含更多信息 例如电话号码 学位 如何根据键 值的存在动态地使用附加列扩展表 我应该与state并在存在时使其可见 或者我应
  • 无法将消息发布到服务工作人员,因为控制器值为空

    我正在尝试做一个website https secure depths 31934 herokuapp com 在 Service Worker 的帮助下可以离线使用 以缓存页面所需的文件 我试图让用户控制他希望缓存的图像 为此 我使用一个
  • 如何从 javascript 错误对象读取错误消息

    有人可以帮我解决以下问题吗 我正在通过 redux 操作进行后调用 如下所示 export const addEmployee firstName surname contactNumber email gt async dispatch
  • D3更新circle-pack数据新节点与现有节点重叠

    我正在关注一般更新模式 http bl ocks org mbostock 3808234但在分层方面存在问题 使用圆形包装布局 我pack新数据 update enter and exit圆形元素 然而 当新元素enter 它们重叠upd
  • JS文件中的System.register是什么意思?

    在 Angular 2 中使用指令时 JS 文件中的 System register 是什么意思 我认为这个问题并不特定于 Angular2 中的指令 它是关于 ES6 TypeScript 和其他使用 SystemJS 的现代编译器的一般
  • 如何用 JavaScript 修复图像透视变形和旋转?

    我有一些用手机拍摄的图像 有没有可以拉直纸张照片并将其压平的 JavaScript 库 例如 我想创建一个矩形图像 该图像没有任何失真 换句话说我想知道如何用 JavaScript 修复透视变形和旋转 例如 我发现下面的示例图像来自this
  • 纯 JS 相当于 Jquery eq()

    jquery 的纯等价物是什么eq 例如 我怎样才能实现 class1 class2 eq 0 text 1254 在纯 JavaScript 中 要获取数组中的元素索引 可以使用 在 JavaScript 中 因此 要重现您的代码 您可以
  • vuejs 模板和 asp.net 部分视图,好的做法吗?

    我在网站中使用 Vue js 并将模板添加到 html 代码中 并将 js 代码添加到单个 js 文件中 所以我不想使用 vue Vuefy Browserfy 方法 而是稍后捆绑并缩小我的 js 文件 由于我必须使用 Asp Net MV
  • 如何将本地文本文件上传到文本区域(网页内)

    我是一名新手程序员 需要一些帮助来弄清楚如何将本地文本文件上传到我正在构建的网站内的文本区域 我非常精通 HTML CSS 对 Javascript JQuery 有相当的了解 而且我刚刚学习 PHP 您能提供的任何帮助我将不胜感激 我有一
  • 使用 JavaScript 防止网页导航离开

    如何使用 JavaScript 防止网页导航离开 Using onunload允许您显示消息 但不会中断导航 因为为时已晚 然而 使用onbeforeunload将中断导航 window onbeforeunload function re
  • Angular 2 将字符串转换为 md5 哈希

    我找到了ts md5 https www npmjs com package ts md5包 但在示例中它有一个hashStr方法 但现在不行了 类型上不存在属性 hashStr Md5 使用该错误后 该错误会记录在我的控制台中 我怎样才能
  • Javascript location.href 到 mailto 触发 GET HTTP,该 HTTP 在 Chrome 中被取消

    我有一个按钮可以触发以下 javascript 函数 function sendEmail var mail mailto email protected cdn cgi l email protection location href m
  • 在 Chrome 开发者工具中禁用调试器语句

    我正在尝试对恶意 JavaScript 进行逆向工程 当我最初加载侧面时 会注入 JS 代码 其中包括 debugger 语句并将断点注入我的 chrome 开发人员控制台 通过stackoverflow阅读 禁用所有断点does not帮
  • 检查浏览器空闲的替代方法

    我有一个简单的网络信息亭 在鼠标未使用 jQuery 移动 30 秒后显示用户操作提示 var i null body wrap mousemove function clearTimeout i overlay fadeOut i set
  • 从请求url获取hash参数

    我有这样的网址 http www coolsite com daily plan id 1 http www coolsite com daily plan id 1解析该字符串并读取哈希值 id 之后的值 的最简单方法是什么 谢谢 在客户
  • 如何将项目插入到特定索引处的空数组中?

    我想将一个项目插入到空数组的指定索引中 我看到有 Array prototype splice 方法 但是 如果我在空数组上使用 splice 它只会添加项目来结束数组 如下所示 var a a splice 3 0 item 3 cons
  • 如何将数据推送到嵌套对象

    如何将另一个元素推入variables来自以下对象的属性 var request name Name id 3 rules name Rule name tags tagId 1 variables variable var1 matchT
  • Array.of 与“[ ]”。何时使用 Array.of 而不是“[ ]”?

    当我发现时我正在读一些书Array of https developer mozilla org en docs Web JavaScript Reference Global Objects Array of 根据 MDN Array o
  • Html5画布最热门的任意形状

    我正在尝试开发可以在画布中渲染图像和文本的程序 我尝试处理画布中图像的点击 但它适用于可矩形图像 我的问题 您是否知道处理单击画布中图像的可见部分 非透明部分 的解决方案或框架 我正在寻找 ActionScript hitTestObjec
  • 如何从 Cloud Functions for Firebase 文件夹读取证书文件

    我正在尝试读取 certs 文件夹下的文件 如下所示 functions certs idp public cert perm 这是我用来读取文件的代码 fs readFileSync path join dirname certs idp

随机推荐