(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(module) : typeof define === 'function' && define.amd ? define(['exports', function (exports) { var module = { exports: {} }; factory(module); exports = module.exports; }]) : (function () { var module = { exports: {} }; factory(module); global.Event = module.exports; }()) })(this, function (module) { /** * 判断某个函数是否由浏览器自身实现 */ function isNative (Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); } // 延迟回调触发器 var delay; { if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { delay = setImmediate; } else if (isNative(typeof Promise !== 'undefined' && Promise)) { delay = function (fn) { Promise.resolve() .then(fn) } } else { delay = function (fn) { setTimeout(fn, 0); } } } /** * 回调函数处理器,用于统一话调用回调 */ function fnHandle (fns) { if (!Array.isArray(fns)) { fns = [fns]; } var handle = function handle() { for (var i = 0; i < fns.length; i++) { fns[i].apply(this, arguments); } } handle.fns = fns; return handle } /* ------------- */ function Event () { // 事件回调存储栈 this.stacks = {} } /** * 绑定事件统一处理器 */ Event.prototype.__bind = function __bind (name, fns) { var fn = fnHandle(fns); if (!this.stacks[name]) { this.stacks[name] = fnHandle(function() { }) } this.stacks[name].fns.push(fn); return fn; } /** * 绑定事件及回调函数 */ Event.prototype.on = function on (name, fns) { this.__bind(name, fns); } /** * 接触绑定事件 */ Event.prototype.off = function on(name) { this.stacks[name] && (this.stacks[name] = fnHandle(function () { })) } /** * 单次绑定,一次触发就失效 */ Event.prototype.once = function once (name, fns) { var fn = this.__bind(name, fns); fn.isOnce = true; } /** * 发布事件,及如果事一次绑定的移除引用调用 */ Event.prototype.emit = function emit (name) { var callback = this.stacks[name]; var args = Array.prototype.slice.call(arguments, 1); if (callback) { delay(function () { callback.apply(this, args); var fns = callback.fns, i = 0; while (fns[i]) { if (fns[i].isOnce) { fns.splice(i, 1); } else { i++ } } }) } } module.exports = Event; });