e = e || window.event用法细节讨论

e = e || window.event是我们在做事件处理时候区分IE和其他浏览器事件对象时常用的写法。但是这行兼容性代码有没有必要出现在所有的事件句柄中呢?标准事件调用方式需要这行代码吗?下边我们做详细讨论。

  在讨论之前,如果有些忘记或者不熟悉事件对象的先参考其他资料,或者看看这个连接的资料http://wenku.baidu.com/view/400a89f4f61fb7360b4c65ca.html

这里作者把四种主要的事件调用方式总结了出来,本文的讨论也是在此之上延伸说明。

  1 <!DOCTYPE HTML>
  2 <html>
  3 <head>
  4     <title></title>
  5     <style type="text/css">
  6     #aa{ border:1px solid #000; width:100px; height:40px; margin-top:50px;}
  7     #bb{ border:1px solid #000; width:500px; height:40px; margin-top:50px;}
  8     #cc{ border:1px solid #000; width:500px; height:40px;}
  9     </style>
 10 </head>
 11 <body>
 12     <div id="aa"></div>
 13     <div id="bb">dfdfddfsd</div>
 14     <div id="cc">gregreger</div>
 15 
 16     <script type="text/javascript">
 17 
 18         document.getElementById("aa").onclick = function (e) {
 19             if (e) alert(e.toString()); // IE6/7/8 e为undefined  IE9中e为W3标准事件对象。
 20             //e = window.event;
 21             alert(e.srcElement.tagName || e.currentTarget.tagName);
 22         }
 23         /*  element.onXXX方式(比较古老,不推荐使用)
 24 
 25         这种方式添加事件IE6/7/8只支持window.event不支持参数传入,
 26         Firefox只支持参数传入不支持其它方式。
 27         IE9/Opera/Safari/Chrome 两种方式都支持。
 28         */
 29 
 30         
 31         var d4 = document.getElementById('bb');
 32         function clk(e) {
 33             alert(e);  // 所有浏览器弹出的信息框显示都是事件对象。
 34             alert(e.srcElement.tagName || e.currentTarget.tagName);
 35             e = e || window.event;
 36             alert(e);  // IE6/7/8中和上个e弹出相同的对象。
 37         } 
 38         if (d4.addEventListener) {
 39             d4.addEventListener('click', clk, false);
 40             alert("addEventListener");
 41         }
 42         if (d4.attachEvent) {
 43             d4.attachEvent('onclick', clk);
 44             alert("attachEvent");
 45         }
 46         /*  addEventListener、attachEvent方式(推荐使用)
 47 
 48         结论:
 49         通常事件句柄里有这句话:e = e || window.event;
 50         但是在这种调用方式(addEventListener、attachEvent方式)中没什么作用,
 51         这是什么原因呢?上边参考文章的总结里指出了原因,即:
 52         “IE6/7/8支持通过window.event获取对象,
 53         通过attachEvent方式添加事件时也支持事件对象作为句柄第一个参数传入”
 54         因为IE6/7/8在attachEvent方式添加事件时同时支持两种方式,所以事件句柄中的参数e在
 55         IE6/7/8中会自动转换为window.event。
 56         这么以来,这句e = e || window.event;在此处就不需要了(个人结论)。
 57 
 58         */
 59 
 60 
 61         /*  
 62         在编写跨浏览器的函数库时,IE和标准事件对象的属性的差异的问题需要解决。
 63         下边抽出相关代码,讨论这个问题在这里的体现。
 64         */
 65         var _E = {
 66             BindEvent: function (object, fun) {
 67                 if (arguments.length == 1) {
 68                     fun = arguments[0];
 69                     object = null;
 70                 }
 71                 var args = Array.prototype.slice.call(arguments, 2);
 72                 return function (event) {
 73                     return fun.apply(object, [fixEvent(event)].concat(args));
 74                 }
 75             }
 76         };
 77         function fixEvent(event) {  // 统一不同浏览器的event对象
 78             if (event) return event;  
 79             event = window.event;
 80             event.pageX = event.clientX + getScrollLeft(event.srcElement);
 81             event.pageY = event.clientY + getScrollTop(event.srcElement);
 82             event.target = event.srcElement;
 83             event.stopPropagation = stopPropagation;
 84             event.preventDefault = preventDefault;
 85             var relatedTarget = {
 86                 "mouseout": event.toElement, "mouseover": event.fromElement
 87             }[event.type];
 88             if (relatedTarget) { event.relatedTarget = relatedTarget; }
 89 
 90             return event;
 91         };
 92         function stopPropagation() { this.cancelBubble = true; };
 93         function preventDefault() { this.returnValue = false; };
 94 
 95         // 测试代码如下
 96         function get(ev) {
 97             alert(ev.pageX);
 98         }
 99         var cc = document.getElementById("cc");
100         var clickHandler = _E.BindEvent(get);
101         cc.attachEvent('onclick', clickHandler);  // IE6/7/8下测试
102         /*
103         结果点击id为cc的div元素后,弹出undefined。说明ev.pageX根本不存在。
104         可是我们在fixEvent()里已经做了事件对象的统一工作。
105         调试会发现:fixEvent()里if (event) return event;这句是执行后就直接return了,
106         这里的event按照道理说应该是undefined,但是事实并不是。
107 
108         //
109         至于原因个人觉得就是这里:因为IE6/7/8在attachEvent方式添加事件时同时支持两种方式,
110         所以事件句柄中的参数会自动转换为window.event。也就是说参数不是undefined
111         
112         //
113         所以在这里用if (event) return event;判断事件对象不妥。
114         (说明:fixEvent()这段代码参考自博客园里cloudgamer的函数库,
115          他里边就是这种写法,个人觉得有错误,希望有兴趣的朋友也做做验证)
116         */
117 
118     </script>
119 </body>
120 </html>

本文转自:http://www.cnblogs.com/huajs/archive/2011/11/10/2244793.html

原文地址:https://www.cnblogs.com/cfhome/p/2942478.html