1  +function(w) {
 2         function Evt() {
 3           return new Evt.prototype.init();
 4         }
 5         Evt.prototype = {
 6           constructor: this,
 7           init: function() {
 8             this.handlers = {}
 9             return this;
10           },
11           add: function(type, fn) {
12             if(typeof type === 'string' && !(type in this.handlers)) {
13               this.handlers[type] = [];    //创建一个事件集
14             }
15             if(typeof fn === 'function') {
16               this.handlers[type].push(fn);    //为当前事件注册函数
17             } else {
18               throw 'the method of argument not a function'
19             }
20             return this;
21           },
22           fire: function(type) {
23             var arrevt = [];
24             var args = [];
25             if(arguments.length > 2) {
26               args = Array.prototype.slice.apply(arguments, [1]);    //获取事件参数
27             }else if(arguments.length > 1) {
28               args = arguments[1];
29             }
30             if(typeof type === 'string' && (type in this.handlers)) {
31               arrevt = this.handlers[type];
32             }
33             for(var i = 0, len = arrevt.length; i < len; i++) {
34               if(args.length > 0) {
35                 //这里本想让事件触发扔到异步队列中去,然而却访问不到i了,
36                 //于是这种操作被我弄得无意义了
           //这里可以改用forEach写法,反正原理一样
37 +function(i) { 38 setTimeout(function() { 39 arrevt[i](args); 40 }, 0); 41 }(i); 42 }else { 43 +function(i) { 44 setTimeout(function() { 45 arrevt[i](); 46 }, 0); 47 }(i); 48 } 49 50 } 51 return this; 52 }, 53 del: function(type, fn) { 54 if(typeof type === 'string' && (type in this.handlers)) { 55 if(typeof fn === 'function') { 56 var arrevt = this.handlers[type]; 57 for(var i = 0, len = arrevt.length; i < len; i++) { 58 if(fn === arrevt[i]) { 59 arrevt.splite(i, 1); //删除该注册函数 60 break; 61 } 62 } 63 } 64 } 65 return this; 66 } 67 } 68 Evt.prototype.init.prototype = Evt.prototype; 69 70 window.evt = new Evt; 71 }(window);

以上代码将实现一个简单的pub/sub模式,一切皆事件,任何行为都是事件,使用方法

//将所要注册的方法交于一个类统一管理, 这里称为接口inf, 
//这种写法略显"浮肿",但可通过bind创建函数并改变内部this指向
      var inf = {
        test: function(data) {
          console.log(data);
        }
      }
//外部注册事件,并调用事件    传参仅支持数组或者对象
evt.add('test', inf.test).fire('test', 'hello, world');