前言:

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

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

问题:

用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",说明匿名函数成功解绑。

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

  1. js从后台取值并绑定到元素上

    用ajax从后台取值不是什么有技术含量的活计,把后台取来的值绑定到Vue对象上也不算难,但每一次向后台拿数据的时候都得写上这么一段代码就十分痛苦了. 于是我写了这么一小段js代码,能够自己根据url去 ...

  2. javascript里你绝对用的上的字符分割函数--原创

    // 在数组内字符为未知情况下,合并和分割的解决方案 var data = [['your name', 'myvalue'], ['myr name', 'thivalue']]; function ...

  3. javascript之事件绑定

    曾经写过一篇随笔,attachEvent和addEventListener,跟本文内容有很多相似之处 本文链接:javascript之事件绑定 1.原始写法 <div onclick=" ...

  4. javascript中事件总结&通用的事件侦听器函数封装&事件委托

    前言: JAVASCRIPT与HTML之间的交互是通过事件来实现的.事件,就是文档或浏览器窗口中发生的一些特定交互瞬间.可以使用侦听器( 或处理程序 )来预定事件,以便事件发生时执行相应的代码.这种在 ...

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

    前言 众所周知,我们在自定义指令时,会指定它的作用域,即scope设置项(默认值为false). 且,scope设置项,可以有三种值,从而也就代表三种不同的作用域,下面我们再来一起回顾下: 指令之sc ...

  6. jQuery 绑定事件及移除绑定事件方法和元素事件列表

    1.jQuery Event 事件:      ready(fn); $(document).ready()注意在body中没有onload事件,否则该函数不能执行.在每个页面中可以有很多个函数被加载 ...

  7. 05 HTML字符串转换成jQuery对象、绑定数据到元素上

    1 要求 将一段 HTML脚本 封装成一个字符串,将这个字符串转换成一个jQuery对象:然后将这个jQuery对象添加到指定的元素中去 2 步骤 定义字符串 var str = '<div i ...

  8. 【jquery】 在异步加载的元素上绑定事件

    最近因为工作关系又重新回归到了jquery的怀抱,发现很多jquery的一些细节处理的部分都忘记了.这里记录一下最近在做项目时频繁遇到的一个问题:给异步加载的元素添加事件绑定. 问题发生的前提是项目前 ...

  9. one(type,[data],fn) 为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。

    one(type,[data],fn) 概述 为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数. 在每个对象上,这个事件处理函数只会被执行一次.其他规则与bind()函数相同.这 ...

随机推荐

  1. Web性能优化:What? Why? How?

    为什么要提升web性能? Web性能黄金准则:只有10%~20%的最终用户响应时间花在了下载html文档上,其余的80%~90%时间花在了下载页面组件上. web性能对于用户体验有及其重要的影响,根据 ...

  2. 一次修改闭源 Entity Provider 程序集以兼容新 EntityFramework 的过程

    读完本文你会知道,如何在没有源码的情况下,直接修改一个 DLL 以去除 DLL 上的强命名限制,并在该程序集上直接添加你的“友元程序集(一种特殊的 Attribute,将它应用在程序集上,使得程序集内 ...

  3. win7安装时,避免产生100m系统保留分区的办法

    在通过光盘或者U盘安装Win7操作系统时,在对新硬盘进行分区时,会自动产生100m的系统保留分区.对于有洁癖的人来说,这个不可见又删不掉的分区是个苦恼.下面介绍通过diskpart消灭保留分区的办法: ...

  4. python黑魔法 -- 内置方法使用

    很多pythonic的代码都会用到内置方法,根据自己的经验,罗列一下自己知道的内置方法. __getitem__ __setitem__ __delitem__ 这三个方法是字典类的内置方法,分别对应 ...

  5. 【原创经验分享】WCF之消息队列

    最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...

  6. 【干货分享】流程DEMO-制度发文和干部任免

    流程名: 制度发文和干部任免  业务描述: 当员工在该出勤的工作日出勤但漏打卡时,于一周内填写补打卡申请.  流程相关文件: 流程包.xml  流程说明: 直接导入流程包文件,即可使用本流程  表单: ...

  7. BPM Domino集成解决方案

    一.需求分析 Lotus Notes/Domino是IBM的协同办公平台,在国内有广泛的用户. 但由于推出年头较早.采用文档数据库等特点, 导致其流程集成能力弱.统计分析难.不支持移动办公等问题,很多 ...

  8. Android之解析XML

    1.XML:可扩展标记语言. 可扩展标记语言是一种很像超文本标记语言的标记语言. 它的设计宗旨是传输数据,而不是显示数据. 它的标记没有被预定义.需要自行定义标签. 它被设计为具有自我描述性. 是W3 ...

  9. 如何使用SHOW WARNINGS?

    1.show warnings:显示上一个语句的错误.警告以及注意.如图:

  10. jQuery.data() 使用方法

    data() 方法向被选元素附加数据,或者从被选元素获取数据.在实际开发中,可以用来记录上一步操作某一对象的值,来给下一步操作做一些判断 $("#btn1").click(func ...