实例来自 JS设计模式开发实例 曾探
记下以后继续参悟
<div id='div1'>aaaa</div>
<script src="jquery-1.10.2.min.js"></script>
<script>
var Event = (function(){
var global = this,Event,_default = 'default';
Event = function(){
var _listen,
_trigger,
_remove,
_slice = Array.prototype.slice,
_shift = Array.prototype.shift,
_unshift = Array.prototype.unshift,
namespaceCache = {},
_create,
find,
each = function( ary, fn ){
var ret;
for ( var i = 0, l = ary.length; i < l; i++ ){
var n = ary[i];
ret = fn.call( n, i, n);
}
return ret;
};
_listen = function( key, fn, cache ){
if ( !cache[ key ] ){
cache[ key ] = [];
}
cache[key].push( fn );
};
_remove = function( key, cache ,fn){
if ( cache[ key ] ){
if( fn ){
for( var i = cache[ key ].length; i >= 0; i-- ){
if( cache[ key ][i] === fn ){
cache[ key ].splice( i, 1 );
}
}
}else{
cache[ key ] = [];
}
}
};
_trigger = function(){
var cache = _shift.call(arguments),
key = _shift.call(arguments),
args = arguments,
_self = this,
ret,
stack = cache[ key ];
if ( !stack || !stack.length ){
return;
}
return each( stack, function(){
return this.apply( _self, args );
});
};
_create = function( namespace ){
var namespace = namespace || _default;
var cache = {},
offlineStack = [], // 离线事件
ret = {
listen: function( key, fn, last ){
_listen( key, fn, cache ); //增加cache集合
if ( offlineStack === null ){
return;
}
if ( last === 'last' ){
offlineStack.length && offlineStack.pop()();
}else{
//离线事件里添加了fn()方法
each( offlineStack, function(){
this();
});
}
offlineStack = null; //订阅时 离线事件清空 下次发布时triger就将会执行fn()
},
one: function( key, fn, last ){
_remove( key, cache );
this.listen( key, fn ,last );
},
remove: function( key, fn ){
_remove( key, cache ,fn);
},
trigger: function(){
var fn,
args,
_self = this;
_unshift.call( arguments, cache ); //arguments 第一个元素添加空数组cache
args = arguments;
fn = function(){
return _trigger.apply( _self, args );
};
//发布者offlineStack为一个空数组表明还没有订阅,为null时表示已经订阅
if ( offlineStack ){
return offlineStack.push( fn );
}
return fn();
}
};
//namespace命名空间默认“default”,namespaceCache[ namespace ]为空时将ret赋值给他,并返回
return namespace ?
( namespaceCache[ namespace ] ? namespaceCache[ namespace ] :
namespaceCache[ namespace ] = ret )
: ret;
};
return {
create: _create,
one: function( key,fn, last ){
var event = this.create( );
event.one( key,fn,last );
},
remove: function( key,fn ){
var event = this.create( );
event.remove( key,fn );
},
listen: function( key, fn, last ){
var event = this.create( );
event.listen( key, fn, last );
},
trigger: function(){
var event = this.create( );
event.trigger.apply( this, arguments );
}
};
}();
return Event;
})();
//发布
Event.trigger( 'click', 1 );
Event.trigger( 'click', 5 );
//订阅
Event.listen( 'click', function( a ){
console.log( a ); // 输出:1 ,5 离线输出
});
Event.trigger( 'click', 6 ); //输出6
/************** 使用命名空间 ********************/
Event.create( 'namespace1' ).listen( 'click', function( a ){
console.log( a ); // 输出:1
});
Event.create( 'namespace1' ).listen( 'click', function( a ){
console.log( a ); // 输出:1
});
Event.create( 'namespace1' ).trigger( 'click', 3 );
Event.create( 'namespace1' ).listen( 'click', function( a ){
console.log( a ); // 输出:1
});
Event.create( 'namespace2' ).listen( 'click', function( a ){
console.log( a ); // 输出:2
});
Event.create( 'namespace2' ).trigger( 'click', 2 );
</script>