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