原理请看:http://www.cnblogs.com/snandy/archive/2011/04/08/2007976.html
直接上自己一步步根据抄袭来的代码的js,自己亲手写了一遍:
var Event = function (){ function _isEmptyObj(obj){ //检查是否为空对象 for(var a in obj){ return false; } return true; } function _each(ary, callback){ //遍历一个数据 每次执行的结果的返回值为假时 进行下次遍历 for(var i=0,len=ary.length; i<len;){ //调用callBck 返回true的话 从头开始遍历,否则继续遍历 callback(i, ary[i]) ? i=0 : i++; } }; //解除绑定事件 function _remove(el, type){ //获取已经绑定的事件集合 var handler = el.listeners[type]['_handler_']; console.log(el.listeners[type]); el.removeEventListener ? el.removeEventListener(type, handler, false) : el.detachEvent('on'+type, handler); //删除事件绑定事件函数 delete el.listeners[type]; //如果为空,那么删除元素上绑定的属性 if(_isEmptyObj(el.listeners)){ delete el.listeners; } } //移除某一类型的事件 function removeEvent(ele,type,fn){ //如果ele没有添加的属性,则事件绑定不存在 if(!ele.listeners) return; //获取一类事件的函数 var listeners = ele.listeners && ele.listeners[type]; if(listeners){ //遍历listeners _each(listeners, function(i, f){ //如果 遍历到的函数与要移除的函数的函数名相同时,截取这个函数 if(f==fn){ return listeners.splice(i, 1); } }); //当绑定事件全被干掉了,就解除绑定的["__handle__"] if(listeners.length == 0){ _remove(ele,type); } } } //添加自定义事件 function addEvent(ele,type,fn){ //给元素加上一个属性,如果存在就等于存在的对象,不存在则为空对象 ele.listeners = ele.listeners || {}; //存储独享的key值为type,存在的话直接就为已有的数组,否则为空数组 var listeners = ele.listeners[type] = (ele.listeners[type] || []); //把这一类事件的回调函数存储起来 listeners.push(fn); //每一个函数的listeners,目的是创造一个函数,使addEventListener和attachEvent的内部this都指向元素本身 if(!listeners["__handle__"]){ listeners["__handle__"] = function (ev){ var ev = ev || window.event; //兼容事件对象 for(var i=0,fn;fn=listeners[i++];){ //调用一类事件所存储的回调函数,handle被调用时,依次调用; fn.call(ele,ev); }; }; ele.addEventListener ? ele.addEventListener(type,listeners["__handle__"],false) : ele.attachEvent("on"+type,listeners["__handle__"]); }; }; //自动触发事件 function dispatch(ele,type){ try{ if(ele.dispatchEvent){ //标准浏览器 var evt = document.createEvent("Event"); evt.initEvent(type,true,true); ele.dispatchEvent(evt); }else{ ele.fireEvent("on"+type); } }catch(e){}; } return { addEvent:addEvent, dispatch:dispatch, removeEvent:removeEvent } }();
这也是一道面试题!