修改attachEvent中this指向/匿名事件处理函数解绑方法

以下文字摘自:http://www.cnblogs.com/cczw/archive/2012/12/06/2805527.html

                         http://www.cnblogs.com/zhenn/archive/2011/02/20/1959018.html


1、修改attachEvent中的this指向

给dom元素绑定事件监听,很easy,即使刚入门的javascript编程人员都可以办到,比如obj.onclick = fn就可以很轻松的监听obj的单击事件,这固然是没有问题的,但是问题就在于在这个监听过程中,很难触发N个代码片段,例如:

1
2
3
obj.onclick = fn1;
obj.onclick = fn2;
...

事实上,如果这么做,fn2会把fn1覆盖,也就是说在单击obj时只会执行fn2中的代码片段,fn1则会被忽略,很显然这样不能满足我们的需求。在考 虑到这个问题的时候,JS已经为我们准备了像attachEvnet、addEventListener这样的方法来满足我们的需求,虽然在不同级别的浏 览器中方法不尽相同,利用对browser的能力检测还是可以轻松的实现一个兼容的方法:

1
2
3
4
5
6
7
8
9
10
11
function  bindEvent(elem,type,fn){
     if (elem.attachEvent){
         elem.attachEvent( "on" +type,fn);
     } else {
         elem.addEventListener(type,fn, false );
     }
}
//调用
bindEvent(obj, "click" ,fn1);
bindEvent(obj, "click" ,fn2);
bindEvent(obj, "mouseover" , function (){alert( this )})   //this->window

这样目的就达到了,当单击obj时,依次执行fn1、fn2。解决了这个问题后,细心的淫们会发现在执行的function中this执行是有问题的,始 终指向window,又不是一个不小的麻烦。那么有没有办法,来解决这个棘手的问题呢,答案是肯定的,这正是我写这篇文章的意义所在,废话!

其实只需对bindEvent稍作加工即可,如下:

1
2
3
4
5
6
7
8
9
10
function  bindEvent(elem,type,fn){
     if (elem.attachEvent){
         elem.attachEvent( "on" +type, function (){
             fn.apply(elem,arguments);
         });
     } else {
         elem.addEventListener(type,fn, false );
     }
}
bindEvent(obj, "mouseover" , function (){alert( this )})  //this->elem

2、匿名函数解绑

2.1  addEventListner 与bind方法

下面来实现click事件2次后,自动解除绑定。

看代码:

复制代码
var dom=document.getElementById("test"),clickt=0;
dom.addEventListener("click",function(e){
    clickt++;
    alert('你摸了我'+clickt+'下了。最多摸2下哦');
    if(clickt>=2){
         this.removeEventListener(e.type,arguments.callee,false);
    }
},false);
复制代码

很多扩展库,比如jquery都可以如此来实现自定义解除绑定:

复制代码
var t=0;
$(".a").bind("click",function(e){
    t++;
    alert('你摸了我'+t+'下了。最多摸2下哦');
    if(t>=2){
         $(this).unbind(e.type,arguments.callee);
    }
}); 
复制代码

2.2  attachEvent 匿名函数解绑

我想要从根本上解决这些问题,就一定抛弃attachEvent这个方法,事实上我也是这样做的,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//绑定事件
function  bindEvent(elem,type,fn){
     if (elem.attachEvent){
         var  typeRef = "_"  + type;
         if (!elem[typeRef]){
             elem[typeRef] = [];
         }
         for ( var  i in  elem[typeRef]){
             if (elem[typeRef][i] == fn){
                 return ;
             }
         }
         elem[typeRef].push(fn);
         elem[ "on" +type] = function (){
             for ( var  i in  this [typeRef]){
                 this [typeRef][i].apply( this ,arguments);
             }
         }  
     } else {
         elem.addEventListener(type,fn, false );
     }
}
 
//移除事件绑定
function  removeEvent(elem,type,fn){
     if (elem.detachEvent){
         if (elem[ "_" +type]){
             for ( var  i in  elem[ "_" +type]){
                 if (elem[ "_" +type][i] == fn){
                     elem[ "_" +type].splice(i,1);
                     break ;
                 }
             }
         }
     } else {
         elem.removeEventListener(type,fn, false );
     }
}

这段代码有点饶人,首先根据type类型给elem注册一个相关的属性_type,来存放elem同种类型事件要执行的代码片段,当然在这个过程中 要先判断这个属性是否已经存在,如果存在,则跳过这一步。然后要遍历这个存放代码片段的数组,判断是否有和要添加的代码片段相同的代码片段,如果有,直接 跳出function。假设在上一步条件不满足的情况下(即代码片段不重复),那么把这个代码片段push到相应的数组中。之后干的事情,我想大家应该很 清楚了,没错,就是把相应数组里的代码片段依次apply到elem下执行。当然,这个过程只有在触发事件的时候,才会发生。

依照这个原理,那么要删除绑定的某个代码片段就很容易做到了,只需要从elem["_"+type]这个数组中把相应的代码片段删除即可。

解释一下为什么这个存放需要绑定代码片段的数组设置为elem的一个属性,其实理由很简单,就是不用声明一个全部变量(数组类型),来管理这个二维的数据结构,这样可以保证bindEvent,removeEvent的高度独立性。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值