自定义事件,就是本身定义事件类型,本身定义事件处理函数。数组
咱们平时操做dom时常常会用到onclick、onmousemove等浏览器特定行为的事件类型。浏览器
封装is自定义事件基本的构思:dom
var eventTarget = { addEvent: function(){ //添加事件 }, fireEvent: function(){ //触发事件 }, removeEvent: function(){ //移除事件 } };
在js默认事件中事件类型以及对应的执行函数是一一对应的,可是自定义事件,须要一个映射表来创建二者之间的联系。函数
如: 这样每一个类型能够处理多个事件函数this
handlers = { "type1":[ "fun1", "fun2", // "..." ], "type2":[ "fun1", "fun2" // "..." ] //"..." }
代码实现:spa
function EventTarget(){ //事件处理程序数组集合 this.handlers={}; } //自定义事件的原型对象 EventTarget.prototype={ //设置原型构造函数链 constructor:EventTarget, //注册给定类型的事件处理程序 //type->自定义事件类型,如click,handler->自定义事件回调函数 addEvent:function(type,handler){ //判断事件处理函数中是否有该类型事件 if(this.handlers[type]==undefined){ this.handlers[type]=[]; } this.handlers[type].push(handler); }, //触发事件 //event为一个js对象,属性中至少包含type属性。 fireEvent:function(event){ //模拟真实事件的event if(!event.target){ event.target=this; } //判断是否存在该事件类型 if(this.handlers[event.type] instanceof Array){ var items=this.handlers[event.type]; //在同一事件类型下可能存在多个事件处理函数,依次触发 //执行触发 items.forEach(function(item){ item(event); }) } }, //删除事件 removeEvent:function(type,handler){ //判断是否存在该事件类型 if(this.handlers[type] instanceof Array){ var items=this.handlers[type]; //在同一事件类型下可能存在多个处理事件 for(var i=0;i<items.length;i++){ if(items[i]==handler){ //从该类型的事件数组中删除该事件 items.splice(i,1); break; } } } } } //调用方法 function fun(){ console.log('执行该方法'); } function fun1(obj){ console.log('run '+obj.min+'s'); } var target=new EventTarget(); target.addEvent("run",fun);//添加事件 target.addEvent("run",fun1);//添加事件 target.fireEvent({type:"run",min:"30"});//执行该方法 123 target.removeEvent("run",fun);//移除事件 target.fireEvent({type:"run",min:"20"});//123
为何要把方法添加到对象原型上?prototype
在构造函数中加属性,在原型中加方法。code
将属性和方法都写在构造函数里是没有问题的,可是每次进行实例化的过程当中,要重复建立功能不变的方法。对象
因为方法本质上是函数,其实也就是在堆内存中又新建了一个对象空间存放存储函数,形成了没必要要的资源浪费。blog
在自己添加会致使每次对象实例化时代码被复制,都须要申请一块内存存放该方法。