Web开发编程网
分享Web开发相关技术

前端面试题:自定义事件

关于事件,我想这也是前端面试中必问的一道题,除了浏览器实现的原生事件之外,今天这一题是想说一说,如何实现一个自定义事件。

题目:如何利用JavaScript实现一个自定义事件,存在on,off,emit三个方法?

这个题目的意义在哪里?我想,应该是对于一些特定的业务逻辑,比如在注册一个“通知”的事件,在与Native交互之后,假设这个交互是在入口级别的页面里,那么如何发送给具体某个业务呢?事件应该是最简单的一种方式,在某个具体的业务中注册一个事件,然后在与Native交互完,拿到某些数据后,然后触发这个事件。

我们来一步一步实现一个最简单的事件类Event,不考虑任何其他复杂的情况。假设在这个Event类的内部有一个this._events = [] 数组来维系整个事件系统,我们分别实现on,off,emit三个方法即可。

on(注册一个事件):

Event.prototype.on = function(type,fun){
    let cbs = this._events[type];
    cbs ? cbs.push(fun) : this._events[type] = [];
        if (!cbs) {
            this._events[type].push(fun)
    }        
}

这里为什么要将this._events设计为二维数组?因为事件可以是多个,但是事件名可能相同。这个逻辑意图非常的明显,根据type参数从this._events中获取是否存在。如果不存在,创建一个type为key的数组,并将事件句柄程序push到数组中。

off(注销一个事件):

Event.prototype.off = function(type,fun){    
    let cbs = this._events[type];    
    //事件列队中无事件
    if (!cbs) {        
            return this;
    }    
        //删除所有的事件
    if (!event && !fun) {        
            this._events = {};        
            return this;
    }    
        //只有事件名称时
    if (event && !fun) {        
            this._events[type] = null;        
            return this;
    }    
        //删除某个事件队列中的某个事件
    let cb;    
        let i = cbs.length;    
        while(i--){
        cb = cbs[i];        
                if (cb === fun || cb.fun === fun) {             
                    cbs.splice(i,1);             
                    break;
        }
    }
}

虽然注销事件方法的逻辑可能相比之下稍许多了些,但它的实现也非常简单,只要只存在事件组key名的情况,或者删除某个事件队列中的某个事件句柄程序即可。

emit(触发一个事件):

Event.prototype.emit = function(type){    
    let cbs = this._events[type];    
    let args = tools.toArray(arguments,1);    
    if (cbs) {        
        let i = 0;        
        let j = cbs.length;        
        for(;i<j;i++){            
            let cb = cbs[i];            
            cb.apply(this,args);
        }
    }
}

逻辑依然非常简单,通过事件名从this._events获取相应的事件句柄程序数组,然后将arguments转成数组,(这里考虑的是可能会传入参数)如果事件句柄程序数组存在,进行循环,再讲args参数apply给每一个取出来的事件句柄程序。

这又是一个“抛砖引玉”,关于事件,还会有更多的业务实现,比如根据组件来依次传递触发,然后建立一个中间的通道,一边订阅,一边发布,它们都向中间通道来注册事件,当临界点来临时,发布者只向中间通道来发布,订阅者根本不需要关注发布者。

未经允许不得转载:WEB开发编程网 » 前端面试题:自定义事件

WEB开发编程网

谢谢支持,我们一直在努力

安全提示:您正在对WEB开发编程网进行赞赏操作,一但支付,不可返还。