你让MSIE与W3C的注册事件真的统一了吗
说起页面元素的事件注册,一般我们都会写一个方法做一个包装,类似如下的方法(好像PPK的书中也是这样封装的)
function addEvent (eventType,listener,oTarget){ if(oTarget.addEventListener){ oTarget.addEventListener(eventType,listener,false); } else if(oTarget.attachEvent){ oTarget.attachEvent('on'+eventType,listener); } }
考虑到MSIE不支持捕获过程,我承认,没法达到真正意义上的统一,但这样做还会出现别的不谐调:
1、this问题:W3C的注册事件,在listener的方法体中,this是指向oTarget的,但MSIE中this还是指向window对象。
2、event对象:W3C的事件模型会在激发事件调用listener的时候传入一个event对象,而MSIE的不会传参,它的event对象是window对象的一个属性,所以我们没法统一listener的函数签名。
接下来,我们重新包装这个方法来修复这两个问题
function addEvent (eventType,listener,oTarget){ if(window.addEventListener){ oTarget.addEventListener(eventType,listener,false); } else if(window.attachEvent){ oTarget.attachEvent( 'on'+type, function(){listener.call(oTarget, window.event);} ); } }
通过call的方式,改变this的指向,并将window.event作为参数传给listener,并且可以统一listener的签名为listener(e),它是接受一个名为e的参数的。
其实这些问题高手们早已解决过了,这是John Resig的版本的部分代码
if(node.attachEvent) { node['e'+type+listener] = listener;//保证listener中的this是引用node node[type+listener] = function(){node['e'+type+listener]( window.event );}//保证event的传入 node.attachEvent( 'on'+type, node[type+listener] ); }