#36 实现一个 EventEmitter


  • 0

    @zhang-lll 咱俩遇到同一个问题~XD


  • 0

    @ScriptOJ 能举个例子么?


  • 0

    @OmnipotenX 每个event都要new 一个Set吧


  • 0

    稍微简洁的写法

    class EventEmitter {
      constructor() {
        this.listeners = {};
      }
      
      on(eventName, func) {
        this.listeners[eventName] || (this.listeners[eventName] = []);
        this.listeners[eventName].push(func);
      }
      
      emit(eventName, ...args) {
        this.listeners[eventName].forEach(func => func(...args));
      }
      
      off(eventName, func) {
        this.listeners[eventName].forEach((item, index) => item === func && this.listeners[eventName].splice(index, 1));
      }
    }
    

  • 0

    class EventEmitter {
      constructor(){
        this._events={}
      }
      on(eventName,listener){
        let events=this._events
        let listeners=events[eventName]=events[eventName]||[]
        listeners.push(listener)
      }
      emit(eventName,...args){
        let listeners=this._events[eventName]
        listeners.forEach((listener)=>{
          listener(...args)
        })
      }
      off(eventName,listener){
        let listeners=this._events[eventName]
        const index=listeners.indexOf(listener)
        if(listener&&index!==-1){
          listeners.splice(index,1)
        }
      }
    }

  • 0

    只写了一次没改就通过测试了,有点惊讶

    class EventEmitter {
    	constructor() {
    		this.handlers = {}
    	}
    
    	on(eventName, callback) {
    		if (!this.handlers[eventName]) {
    			this.handlers[eventName] = []
    		}
    		this.handlers[eventName].push(callback)
    	}
    
    	emit(eventName, ...params) {
    	    if (this.handlers[eventName]) {
    		for (var i = 0; i < this.handlers[eventName].length; i++) {
    		    this.handlers[eventName][i](...params)
    		}  
    	    }	
    	}
    
        off(eventName, callback) {
        	if (this.handlers[eventName]) {
        		for (var i = 0; i < this.handlers[eventName].length; i++) {
        			if (this.handlers[eventName][i] === callback) {
        				break;
        			}
        		}
        		this.handlers[eventName].splice(i, 1)
        	}
        }
    
    }
    

  • 0

    多加了一个once的实现

    class EventEmitter {
      constructor() {
        this.eventHub = [];
      }
      on(type, fn) {
        if(!this.eventHub[type]) this.eventHub[type] = []; // 如果type队列为空,创建新数组
        this.eventHub[type].push(fn);
      }
      emit(type, ...args) {
        if(this.eventHub[type].length) this.eventHub[type].forEach(fn => fn(...args));
      }
      off(type, fn) {
        if(this.eventHub[type].length) {
          const index = this.eventHub[type].indexOf(fn);
          this.eventHub[type] = [...this.eventHub[type].slice(0, index), ...this.eventHub[type].slice(index + 1)];
        }
      }
      once(type, fn) {
        const fnOnce = (...args) => {
          fn(...args);
          this.off(type, fnOnce);
        };
        this.on(type, fnOnce);
      }
    }
    
    

  • 0

    一开始直接没有读懂,真是惭愧,看了各位代码,以及讲解,才明白过来,惭愧的很啊

    class EventEmitter {
      /* TODO */
      constructor () {
        // 存储 监听名eventName,函数func
        this.handleFun = {}
      }
      
      
      on (eventName, func) {
        let handle = this.handleFun[eventName] || []
        
        handle.push(func)
        // 第一次是没有的,需要赋值给他
        this.handleFun[eventName] = handle
      }
      
      
      off (eventName, func) {
        // 需要根据函数体func是否相同,来进行排除
        // 先判断 名,再判断体
        let handle = this.handleFun[eventName] || []
        
        const index = handle.indexOf(func)
        if ( index > -1) handle.splice(index, 1)
        
      }
      
      emit (eventName, ...rest) {
        let handle = this.handleFun[eventName] || []
        
        handle.map(func => {
          func(...rest)
        })
      }
      
      
    }
    
    

  • 0

    class EventEmitter {
        constructor() {
            this.events = {};
        }
        on(eventName,func) {
            if(!this.events[eventName]) {
                this.events[eventName] = [];
            }
            this.events[eventName].push(func);
        }
    
        emit(eventName,...args) {
            if(!this.events[eventName]) {
                return false;
            } else {
                this.events[eventName].forEach(func => {
                    func.call(this,...args);
                });
            }
        }
        off(eventName,func) {
            if(!this.events[eventName]) {
                return false;
            } else {
                this.events[eventName] = this.events[eventName].filter((f)=>{
                    return f!==func;
                })
              
            }
        }
    }
     
    
    

    报错:
    如果用同一个函数监听同一个事件多次,off 的时候只删除一次

    不是很懂这个意思,求解答


  • 2

    给大家说一下我的思路把,需要定义一个对象,用来存储,事件名,和事件
    事件名是对象属性,每一个事件名对应一个存储处理函数的数组
    on就是把事件存储到对象中
    emit就是在对象中调用参数对应的事件
    off就是删除对应的处理函数

    class EventEmitter {
      constructor () {
        this.events = {}
      }
      on (eventName, callback) {
        if (!this.events[eventName]) {
          this.events[eventName] = []
        }
        if (callback) {
          this.events[eventName].push(callback)
        }
      }
      emit (eventName, ...params) {
        let e = this.events[eventName]
        e.forEach((item) => {
          item(...params)
        })
      }
      off (eventName, func) {
        let e = this.events[eventName]
        let index = 0
        if (e) {
          index = e.findIndex((item) => item === func)
        }
        e.splice(index, 1)
      }
    }
    
    

  • 0

    class EventEmitter {
    constructor(){
        this.listeners={}
      }
      on(eventName,func){
        if(!this.listeners[eventName]){
          this.listeners[eventName]=[].concat(func)
        }else{
          this.listeners[eventName].push(func)
        }
      }
    
      emit(eventName,...rest){
        if(this.listeners[eventName]){
          this.listeners[eventName].map(event=>{
            event(...rest)
          })
        }
      }
      off(eventName,func){
        if(this.listeners[eventName]){
          const index = this.listeners[eventName].indexOf(func)
          if(index!=-1){
            this.listeners[eventName].splice(index,1)
          }
        }
      }
    }
    
    

  • 0

    简单判断了一下类型与要删除函数是否存在

    class EventEmitter {
      constructor() {
        this.listener = {}
      }
      
      on(ename, fn) {
        this.listener[ename] ? this.listener[ename].push(fn) : (this.listener[ename] = [fn])
      }
      
      emit(ename, ...args) {
        if (this.listener[ename]) {
          for (const fn of this.listener[ename]) {
            if (typeof fn === 'function') {
              fn(...args)
            }
          }
        }
      }
      
      off(ename, fn) {
        if (this.listener[ename] && this.listener[ename].indexOf(fn) !== -1) {
          this.listener[ename].splice(this.listener[ename].indexOf(fn), 1)
        }
      }
    }
    
    

  • 0

    class EventEmitter {
        constructor() {
            this.cbs = {}
        }
    
        on (eventName, func) {
            if (this.cbs[eventName]) {
                this.cbs[eventName].push(func) 
            } else {
                this.cbs[eventName] = [func]
            }
        }
    
        emit (eventName, ...args) {
            let fns = this.cbs[eventName] || []
            fns.forEach(fn => {
                fn.apply(this, args)
            })
        }
    
        off (eventName, func) {
            if (this.cbs[eventName]) {
                this.cbs[eventName].splice(this.cbs[eventName].indexOf(func), 1)
            }
        }
    }

  • 0

    现场笔试的话,真的够呛啊,不上机调试无法写代码=..=

    class EventEmitter {
      constructor() {
        this.events = {}
      }
    
      on (eventName, callback) {
        this.events[eventName] = (this.events[eventName] || []).concat(callback)
      }
    
      emit (eventName, ...args) {
        (this.events[eventName] || []).map(func => func(...args))
      }
    
      off (eventName, callback) {
        const pos = (this.events[eventName] || []).indexOf(callback)
        if (pos > -1) this.events[eventName].splice(pos, 1)
      }
    }
    

  • 0

    class EventEmitter {
      constructor() {
        this.events = {}
      };
      on(eventName, func) {
        if (!this.events[eventName]) {
          this.events[eventName] = []
        }
        this.events[eventName].push(func);
      };
      emit(eventName, ...params) {
        const events = this.events[eventName];
        if (events) {
          events.forEach(event => {
            event.apply(this, params)
          })
        }
      };
      off(eventName, func) {
        if (this.events[eventName]) {
          if (!func) {
            this.events[eventName] = []
          } else {
            this.events[eventName].splice(this.events[eventName].indexOf(func), 1)
          }
        }
      }
    }
    

  • 0

    #自己试没问题,不知道为什么还是会报错。。。

    class EventEmitter {
      constructor(){
        this.events = Object.create(null)
      }
      on(eventName, func) {
        let _events = this.events
        if(!(eventName in _events)){
          _events[eventName] = new Set()
        }
        _events[eventName].add(func)
      }
      emit(eventName, ...args){
        let _events = this.events
        if(eventName in _events){
          for(const func of _events[eventName].values()){
            func.apply(null, args)
          }
        }
      }
      off(eventName, func) {
        let _events = this.events
        if(eventName in _events){
          _events[eventName].delete(func)
        }
      }
    }
    

  • 0

    貌似不行额,报错,但是本地可以
    class EventEmitter {
    constructor(){
    this.Events = [];
    }
    on(name, fnc){
    this.Events.filter(i=>{
    return i.name === name && i.fnc === fnc
    }).length>0?'':this.Events.push({name, fnc})
    }
    emit(name, ...args){
    this.Events.forEach(i=>{
    if(i.name === name){
    i.fnc(...args)
    }
    })
    }
    off(name, fnc){
    this.Events = this.Events.filter(i=>{
    return !(i.name === name && i.fnc === fnc)
    })
    }
    }


  • 0

    class EventEmitter {
      constructor() {
            this.event = {}
        }
        on(eventName, func) {
            if(eventName === '' || typeof func !== 'function') return false
            const _event = this.event
            _event[eventName] = _event[eventName] || []
            _event[eventName].push(func)
        }
        emit(eventName, ...arg) {
            this.event[eventName].forEach(element => {
                element.apply(this, arg)
            })
        }
        off(eventName, func) {
            const _event = this.event
            _event[eventName].forEach((ele, index) => {
                if(ele === func) {
                    _event[eventName].splice(index, 1)
                    return
                } 
            })
        }
    }
    

  • 0

    @菠萝苹果糖 我也是一样的问题


  • 1

    class EventEmitter {
      constructor() {
        this.events = [];
      }
      on(eventName, func) {
        this.events.push({ [eventName]: func });
      }
      emit(eventName, ...args) {
        for (let event of this.events) {
          if (event.hasOwnProperty(eventName))
            event[eventName].apply(null, ...args);
        }
      }
      off(eventName, func) {
        for (let index in this.events) {
          if (
            this.events[index].hasOwnProperty(eventName) &&
            this.events[index][eventName] === func
          ) {
            this.events.splice(index, 1);
          }
        }
      }
    }
    

登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待