JavaScript移除绑定在元素上的匿名事件处理函数

前言:

面试的时候有点蒙,结束之后想想自己好像根本就误解了面试官的问题,因为我理解的这个问题本身就没有意义。但是当时已经有一些思路,但是在一个点上被卡住。

结束之后脑子瞬间灵光,想出了当时没有迈出的那一小步。所以不想计较这个问题本身的意义,单纯的想要把这个我理解错了的问题解决,就当是满足自己一个小小的愿望吧。

问题:

用addEventListener()和attachEvent()给一个DOM元素绑定事件处理程序时,如果传入一个匿名函数,那么用相应的removeEventListener()和detachEvent()是无法将这个匿名的处理程序解除绑定的。所以我们用的时候应该传入一个函数表达式。

那么,如果我就是想使用匿名函数进行绑定和解绑,怎么解决?

思路:

既然这两个函数都高冷的说明了不接受相同的匿名函数进行解绑,那么就只能另寻出路,不能靠它来管理事件了。

所以需要一个自定义的对象来管理事件。

事件处理程序的本质就是,当一个事件在一个对象上发生时,执行监听这个事件的函数。

翻译一下:

一个DOM元素可能被绑定多个事件类型的处理程序。比如click的时候颜色改变,mouseover的时候变大。

一个事件类型可能绑定多个事件处理程序。比如mouseover的时候又变色又变大。

所以,这个事件对象应该有一个属性用来存储这个DOM元素上绑定的所有事件处理程序,还应该有两个方法,一个用来添加,一个用来删除。

{
handlers:{
type1:[handler1,handler2],
type2:[handler1,handler2],
...//其他事件类型和对应的事件处理函数
},
on:function(){},
off:function(){}
}

当一个事件发生时,就调用这个对象里面对应的事件类型的数组里面的所有函数。

所以绑定事件就是往对应的数组里面添加函数,解除绑定事件就是把这个函数从这个数组里面删掉。

那么怎么保证操作的是那个正确的DOM元素呢?

显然,每个DOM元素都应该需要一个这样的对象,用于管理自己的事件处理程序。

每个对象都有的东西,那不就是他的属性嘛。(而我当时就被卡在了这里)。

实现:

每个DOM元素都需要这样一个对象,而且每个对象中的on()和off()方法都是相同的,所以需要一个构造函数,把这两个方法放到他的原型对象中去。

function EventManage(){
  this.handlers={}
}
EventManage.prototype={
  on:function(type,handler){
    if(!this.handlers[type]){
      this.handlers[type]=[handler];
      return true;  //避免添加多个事件
    }else{
      this.handlers[type].push(handler);
    }
  },
  off:function(type,handler){
    for(var i=0,len=this.handlers[type].length;i<len;i++){
      if(this.handlers[type][i].toString()==handler.toString()){
        this.handlers[type].splice(i,1);
      }
    }
  }
}

每个对象有了这两个方法,就可以自行添加和移除事件处理程序了,但是,监听事件,还是要靠JavaScript提供的方法,所以借用addEventListner()和attachEvent()来监听事件:

var EventUtil={};
EventUtil.on=function(ele,type,handler){
  if (!ele.event) {
    ele.event=new EventManage();
  }
  var isNewType=ele.event.on(type,handler);
  var fire=function(){
      for(var i=0,len=ele.event.handlers[type].length;i<len;i++){
        ele.event.handlers[type][i]();
      }
    };
  if (isNewType) {
    if (ele.addEventListener) {
      ele.addEventListener(type,fire,false);
    }else{
      ele.attachEvent("on"+type,fire);
    }
  }
}
EventUtil.off=function(ele,type,handler){
  ele.event.off(type,handler);
}

这里要注意一个问题,每次使用EventUtil.on()时都会重新定义一个fire函数,addEventListener()就会给相同的事件类型添加多个相同的事件处理程序,所以需要判断一下这个事件类型是不是新增的,如果是的话再用addEventListener()来监听这个事件类型。

使用示例:

var btn=document.getElementById("btn");

EventUtil.on(btn,"click",function(){
  console.log("11");
});
EventUtil.on(btn,"click",function(){
  console.log("22");
});
EventUtil.off(btn,"click",function(){
  console.log("11");
});

当点击btn时,只打印了"22",说明匿名函数成功解绑。

时间: 2024-10-05 05:31:13

JavaScript移除绑定在元素上的匿名事件处理函数的相关文章

AngularJS之一个元素上绑定多个指令作用域

前言 众所周知,我们在自定义指令时,会指定它的作用域,即scope设置项(默认值为false). 且,scope设置项,可以有三种值,从而也就代表三种不同的作用域,下面我们再来一起回顾下: 指令之scope scope: false 默认值,指令不会新建一个作用域,使用父级作用域. scope: true 指令会创建一个新的子作用域,原型继承于父级作用域. scope: {…} 指令会新建一个隔离作用域,不会原型继承父作用域. 好了,通过上面,我们很容易知道,在一个元素绑定一个指令,那么仅仅看这

off() 方法 与 unbind() 方法移除绑定事件的处理程序。one()函数用于为每个匹配元素的一个或多个事件绑定一次性事件处理函数

off() 方法移除用.on()绑定的事件处理程序. unbind() 方法移除用.bind()绑定的事件处理程序. 从 jQuery 1.7开始, .on() 和 .off()方法是最好的元素上附加和移除事件处理程序的方法. 常用原型区别: .unbind( eventType [, handler ] ) .off( events [, selector ] [, handler ] ) off: http://www.365mini.com/page/jquery-off.htm unbi

把多个JavaScript函数绑定到onload事件处理函数上的技巧

一,onload事件发生条件 用户进入页面且页面所有元素都加载完毕.如果在页面的初始位置添加一个JavaScript函数,由于文档没有加载完毕,DOM不完整,可能导致函数执行错误或者达不到我们想要的效果. 二,绑定多个函数到onload事件上 1,先展示一个错误的做法 1 window.onload = firstFunction; 2 window.onload = secondFunction; 实际执行过程中,只有最后一个函数被执行,因为每个事件处理函数只能绑定一条指令. 2,使用一个匿名

鼠标移到元素上指针变为不可用状态

鼠标移到元素上指针变为不可用状态:鼠标的指针状态与很多种,分别代表着不同的含义,下面介绍一下如何实现当鼠标悬浮于一个元素的时候,鼠标指针会变味不可用状态,代码实例如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/" />

sharepoint 2013 webservice 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性

在调用webservice返回数据的时候,?出现以下错误: 已超过传入消息(65536)的最大消息大小配额.若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性 这个就需要在调用webservice的解决方案中,在web.config或者app.config中配置一下: <?xml version="1.0" encoding="utf-8" ?> <configuration> <startup&g

jQuery 判断元素上是否绑定了事件

我研究了一下之后发现,jQuery都将事件缓存起来了,其实也是为了防止内存溢出以及页面unload的时候的速度,也包括多函数触发,方便管理等诸多好处,具体可以参考此文. jQuery会在window.unload的时候卸载所有绑定过的事件,释放内存的. OK,言归正传.判断元素上是否绑定过事件用如下语句 jQuery.data(elem,"events")[type] //老版本也能用 $(elem).data("events")[type] //1.2.3以后才能

WCF 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。

在做图片查询的时候,报错 已超过传入消息(65536)的最大消息大小配额.若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性. 因为图片保存在数据库里,所以数据量比较大. WCF默认传输值是65536字节(64KB),这也太小了,我直接改成50M(52428800字节),网上说最大是支持2147483647字节,但是maxReceivedMessageSize属性是Long类型的,应该比这个还要大. 注意,只有TCP.IPC和基本的HTTP绑定才支持流操作,

WebService 之 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。

在使用 WCF 中,遇到如下问题: 已超过传入消息(65536)的最大消息大小配额.若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性. 问题说明: 客户端调用 WCF 返回数据量大时,局域网没有问题(客户现场发现一台机器有问题,具体原因不详.),发布到外网有问题. VS2012 Debug 捕获到的异常信息为:在 HTTP 通道上传输数据时发生错误(无法从传输连接中读取数据: 连接已关闭). WCFStorm 工具返回的异常为:已超过传入消息(65536)

jQuery查看dom元素上绑定的事件列表

作为技术狂热分子的职业本能,看到一个技术产品的功能,总会忍不住想知道它是怎么被实现的.比如我每每看到别人网站一个很炫的界面或者很酷的功能,就忍不住打开了浏览器的控制台... 好,不扯远,说说当你想看到网站上某个元素绑定的事件函数的代码时应该怎么做吧. 查看原生绑定的事件函数代码 所谓原生就是通过addEventListener方法绑定到dom元素上.这个好办: 审查绑定事件的元素(对着它右键->审查元素) 在弹出的Elements视图的控制台,右侧点击“Event Listeners”页签 然后