//工具函数,判断所属类型,判断是否是null或者undefined
const toString = Object.prototype.toString;
const isType = obj => toString.call(obj).slice(8, -1).toLowerCase();
const isArray = obj => Array.isArray(obj) || isType(obj) === "array";
const isNullOrUndefined = obj => obj === null || obj === undefined;
/**
* 添加事件
* @param {*} type 监听事件的名称
* @param {*} fn 监听事件对应的方法
* @param {*} context 改变this的指向/执行的主体
* @param {*} once 是否只执行一次
*/
const _addListener = function(type, fn, context, once) {
if (typeof fn != "function") {
throw new TypeError("fn 必须是一个函数");
}
fn.context = context;
fn.once = !!once;
const event = this._events[type];
//如果只执行一次, this._events[type] 将是一次函数
if (isNullOrUndefined(event)) {
this._events[type] = fn;
} else if (typeof event === "function") {
//如果已经存在(监听)一个函数,则this._events[type]将是一个数组
this._events[type] = [event, fn];
} else if (isArray(event)) {
//如果存在(监听)多个函数(数组),则push
this._events[type].push(fn);
}
return this;
}
//EventEmitter类
class EventEmitter {
constructor() {
//初始化_events属性
if (isNullOrUndefined(this._events)) {
this._events = Object.create(null);
}
}
//添加事件
addListener(type, fn, context) {
return _addListener.call(this, type, fn, context);
}
//可执行多次
on(type, fn, context) {
return this.addListener(type, fn, context);
}
//执行一次
once(type, fn, context) {
return _addListener.call(this, type, fn, context, true);
}
//事件触发
emit(type, ...rest) {
if (isNullOrUndefined(type)) {
throw new Error("emit必须接收至少一个参数");
}
const events = this._events[type];
if (isNullOrUndefined(events)) return false;
if (typeof events === "function") {
//用call改变this的指向指向events.context主体,否则指向null
events.call(events.context || null, rest);
//执行完毕判断是否只执行一次,是则移除
if (events.once) {
this.removeListener(type, events);
}
} else if (isArray(events)) {
events.map(e => {
e.call(e.context || null, rest);
if (e.once) {
this.removeListener(type, e);
}
})
}
return true;
}
//事件移除
removeListener(type, fn) {
if (isNullOrUndefined(this._events)) return this;
if (isNullOrUndefined(type)) return this;
if (typeof fn !== "function") {
throw new Error("fn 必须是一个函数");
}
const events = this._events[type];
if (typeof events === "function") {
events === fn && delete this._events[type];
} else {
const findIndex = events.findIndex(e => e === fn);
if (findIndex === -1) return this;
if (findIndex === 0) {
events.shift();
} else {
events.splice(findIndex, 1);
}
//如果只剩下一个监听者,则把数组变为函数
if (events.length === 1) {
this._events[type] = events[0];
}
}
return this;
}
//删除所有事件
removeAllListeners(type) {
if (isNullOrUndefined(this._events)) return this;
//如果没有指定type,则删除全部
if (isNullOrUndefined(type)) this._events = Object.create(null);
const events = this._events[type];
if (!isNullOrUndefined(events)) {
//判断是否只剩下最后一个事件
if (Object.keys(this._events).length === 1) {
this._events = Object.create(null);
} else {
delete this._events[type];
}
}
return this;
}
//监听队列
listeners(type) {
if (isNullOrUndefined(this._events)) return [];
const events = this._events[type];
return isNullOrUndefined(events) ? [] : (typeof events === "function" ? [events] : events.map(o => o));
}
//监听者数量
listenerCount(type) {
if (isNullOrUndefined(this._events)) return 0;
const events = this._events[type];
return isNullOrUndefined(events) ? 0 : (typeof events === "function" ? 1 : events.length);
}
eventNames() {
if (isNullOrUndefined(this._events)) return [];
return Object.keys(this._events);
}
}
参考自https://www.php.cn/js-tutoria... 作者:php中世界最好的语言
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。