MST

星途 面试题库

面试题:基于高阶函数和箭头函数构建可复用的事件监听系统

在 JavaScript 环境下,利用高阶函数和箭头函数设计一个通用的事件监听系统。该系统需要具备添加事件监听器、移除事件监听器以及触发事件等功能,并且要考虑到事件作用域、事件委托等相关要点,写出完整的代码实现及必要的注释说明。
38.0万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
// 创建一个事件监听系统的类
class EventEmitter {
    constructor() {
        // 用于存储事件和对应的监听器
        this.events = {};
    }

    // 添加事件监听器的方法
    on(eventName, callback, context) {
        // 如果该事件名对应的监听器数组不存在,则创建一个新的数组
        if (!this.events[eventName]) {
            this.events[eventName] = [];
        }
        // 将监听器(包括回调函数和作用域)添加到对应的事件数组中
        this.events[eventName].push({ callback, context });
    }

    // 移除事件监听器的方法
    off(eventName, callback) {
        // 如果该事件名对应的监听器数组存在
        if (this.events[eventName]) {
            // 使用高阶函数filter过滤掉要移除的监听器
            this.events[eventName] = this.events[eventName].filter(listener => listener.callback!== callback);
        }
    }

    // 触发事件的方法
    emit(eventName, ...args) {
        // 如果该事件名对应的监听器数组存在
        if (this.events[eventName]) {
            // 遍历并执行所有该事件的监听器
            this.events[eventName].forEach(listener => {
                const { callback, context } = listener;
                // 使用call方法来确保回调函数在指定的作用域内执行
                callback.call(context, ...args);
            });
        }
    }
}

// 示例使用
// 创建一个事件发射器实例
const emitter = new EventEmitter();

// 添加一个事件监听器
emitter.on('testEvent', function (data) {
    console.log(`在事件作用域 ${this.name} 中接收到数据:`, data);
}, { name: '示例作用域' });

// 触发事件
emitter.emit('testEvent', 'Hello, Event System!');

// 移除事件监听器
emitter.off('testEvent', function (data) {
    console.log(`在事件作用域 ${this.name} 中接收到数据:`, data);
}, { name: '示例作用域' });

// 再次触发事件,监听器已移除,不会有输出
emitter.emit('testEvent', 'Hello, Event System!');

代码说明

  1. EventEmitter 类

    • constructor:初始化一个空的 events 对象,用于存储事件和对应的监听器数组。
    • on 方法
      • 接受 eventName(事件名)、callback(回调函数)和 context(事件作用域)作为参数。
      • 检查 events 对象中是否存在指定的 eventName,如果不存在则创建一个空数组。
      • 将监听器(包含 callbackcontext)添加到对应的事件数组中。
    • off 方法
      • 接受 eventNamecallback 作为参数。
      • 检查 events 对象中是否存在指定的 eventName,如果存在则使用 filter 方法过滤掉要移除的监听器。
    • emit 方法
      • 接受 eventName 和可变数量的参数 ...args
      • 检查 events 对象中是否存在指定的 eventName,如果存在则遍历并使用 call 方法在指定的 context 作用域内执行所有监听器,并传递参数。
  2. 示例使用

    • 创建一个 EventEmitter 实例 emitter
    • 使用 on 方法添加一个 testEvent 事件的监听器,指定了事件作用域。
    • 使用 emit 方法触发 testEvent 事件,并传递数据。
    • 使用 off 方法移除 testEvent 事件的监听器。
    • 再次触发 testEvent 事件,由于监听器已移除,不会有任何输出。

这样就实现了一个基本的通用事件监听系统,涵盖了添加事件监听器、移除事件监听器以及触发事件的功能,并考虑了事件作用域。如果要考虑事件委托,可以在 emit 方法中添加逻辑,例如在触发父级事件时,判断是否需要同时触发子级事件等,这里暂未详细展开事件委托相关代码,如需进一步实现可根据具体需求修改。