Write a class or function `createEventEmitter()` that supports `on(event, callback)`, `emit(event, ...args)`, and `off(event, callback)` methods.
Problem Statement
Examples
Input: const ee = createEventEmitter(); ee.on("event", fn); ee.emit("event", data);
Output: fn invoked with data
Explanation: Publisher-subscriber event dispatcher.
Complexity
Time Complexity: O(N)
Space Complexity: O(1)
Hints
Editorial & Approach
Problem Overview & Intuition
To solve Event Emitter, we consider the execution characteristics of JavaScript engines. Write a class or function `createEventEmitter()` that supports `on(event, callback)`, `emit(event, ...args)`, and `off(event, callback)` methods. By utilizing idiomatic language constructs and clean algorithmic principles, we can accomplish this with optimal time and memory usage.
Step-by-Step Approach
- Understand Problem Contract: Identify input arguments, return type expectations, and edge cases (empty inputs, nullish values).
- Choose Core Mechanism: Use modern JavaScript patterns (store listeners in a map where keys are event names and values are arrays of callbacks).
- Implement Logic: Handle state and transformations efficiently (emit calls all callbacks registered for the event).
- Return Result: Ensure proper return format and preserve caller context if applicable.
Optimal Implementation (JavaScript)
function createEventEmitter() {
const events = {};
return {
on(event, cb) {
if (!events[event]) events[event] = [];
events[event].push(cb);
},
emit(event, ...args) {
(events[event] || []).forEach(cb => cb(...args));
},
off(event, cb) {
if (events[event]) {
events[event] = events[event].filter(fn => fn !== cb);
}
}
};
}
Complexity Analysis
Edge Cases & Corner Traps Handled
- Empty or boundary inputs (empty arrays, strings, zero length).
- Type checks and unexpected values (e.g.
null,undefined, negative numbers). - Closure preservation and memory isolation between separate invocations.