34Implement an EventTarget-style custom event system
mediumAbout 35 minutesCodingeventsclassesdom-apis
Problem
The DOM's EventTarget behaves differently from a Node-style emitter. Implement a small version of it without using the built-in EventTarget:
class MyEvent:new MyEvent(type, { cancelable = false, detail = null })withtype,detail,target,defaultPrevented,preventDefault()andstopImmediatePropagation().class MyEventTargetwithaddEventListener(type, listener, options),removeEventListener(type, listener)anddispatchEvent(event).
const cart = new MyEventTarget();
cart.addEventListener("checkout", (event) => {
if (event.detail.total === 0) event.preventDefault();
});
const ok = cart.dispatchEvent(new MyEvent("checkout", { cancelable: true, detail: { total: 0 } }));
ok; // false, a listener cancelled itRequirements
- Adding the same listener twice for the same type has no effect (unlike a Node emitter).
- A listener can be a function or an object with a
handleEvent(event)method. options.onceremoves the listener after its first call.dispatchEventsetsevent.targetto the target, calls listeners in order withthisset to the target (for functions), and returnsfalseifpreventDefault()was called on a cancelable event, otherwisetrue.preventDefault()does nothing on events that are not cancelable.stopImmediatePropagation()stops the remaining listeners.- A listener removed during dispatch, before its turn, is not called.
Try it yourself
Write your solution, run it, then submit to check it against the tests.
solution.jsJavaScript
Press Run or ⌘ Enter to execute your code.
Step-by-step
Store type, detail and cancelable. preventDefault() sets defaultPrevented only when the event is cancelable. stopImmediatePropagation() sets an internal flag that dispatch checks.
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 5 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.