最近一直在做秋招的笔试题,EventEmitter居然出现过几次了,说明它还是很重要的,就学了一下,JavaScript源代码还是挺好理解的。
对于Event事件大家应该都很熟悉,比如dom中的button,可以通过addEventListener/attachEvent(IE)添加click事件处理。而一般的object对象是没有事件派发功能的,基于此需求,实现了一个EventEmitter。代码如下:
1 //JS源代码
2 function EventEmitter() {
3 //存放事件和对应的处理方法
4 this.handles = {};
5 }
6 EventEmitter.prototype = {
7 //传入事件类型type和事件处理handle
8 //实现事件订阅on
9 on: function(type, handle) {
10 if (!this.handles[type]) {
11 this.handles[type] = [];
12 }
13 this.handles[type].push(handle);
14 //console.log(handle);
15 },
16 emit: function() {
17 //通过传入参数获取事件类型
18 var type = Array.prototype.shift.call(arguments);
19 if (!this.handles[type]) {
20 return false;
21 }
22 for (var i = 0; i < this.handles[type].length; i++) {
23 var handle = this.handles[type][i];
24 handle.apply(this, arguments);
25 //console.log(arguments);
26 }
27 },
28 off: function(type, handle) {
29 handles = this.handles[type];
30 if (handles) {
31 if (!handle) //不存在handle参数
32 handles.length = 0; //清空数组
33 } else {
34 for (var i = 0; i < handles.length; i++) {
35 if (handles[i] == handle)
36 handles.splice(i, 1);
37 }
38 }
39 }
40 };
测试代码:
1 var em = new EventEmitter();
2 em.on('mm',function (name) {
3 console.log("mm:"+name);
4 });
5 em.emit('mm','哈哈哈哈');
6 //console.log(em);
7 console.log('===============');
8 var p2 = new EventEmitter();
9 var fn = function (name) {
10 console.log('mm2: '+ name);
11 };
12 var fn2 = function (name) {
13 console.log('mm222: '+ name);
14 };
15 p2.on('mm2', fn);
16 p2.on('mm2', fn2);
17 p2.emit('mm2','哈2哈2哈2哈2');
18 console.log('-------------');
19 p2.off('mm2', fn);
20 p2.off('mm2');
21 p2.emit('mm2','哈2哈2哈2哈2');
22 console.log('-------------');
23 p2.off('mm2');
24 p2.emit('mm2','哈2哈2哈2哈2');
25 console.log('-------------');
测试结果:
除此之外,node.js版本的EventEmitter也是很有用的。代码如下:
1 var eventEmitter = require("events");
2 var myEmitter = new eventEmitter();
3 myEmitter.on('begin', function() {
4 console.log('begin');
5 });
6 myEmitter.on('begin', function() {
7 console.log('begin2');
8 });
9 myEmitter.on('end', function() {
10 console.log('end');
11 });
12 myEmitter.emit('end'); //end
13 //可以注册多个同名事件,都会触发
14 myEmitter.emit('begin'); //begin begin2
15 console.log(myEmitter.eventNames()); //[ 'begin', 'end' ] ,同名的只输出一个