Skip to content

Instantly share code, notes, and snippets.

@Lcfvs
Last active January 23, 2022 18:05
Show Gist options
  • Save Lcfvs/94baad13db7005295bbd0cb81a5260e1 to your computer and use it in GitHub Desktop.
Save Lcfvs/94baad13db7005295bbd0cb81a5260e1 to your computer and use it in GitHub Desktop.
Event listening avoiding memory leaks & associating a weak context
const { assign, create, freeze } = Object
const contexts = new Map()
export const capture = true
export const once = true
export const passive = true
export const context = (listener, event) => {
const { currentTarget, target, type } = event
return contexts.get(type)?.get(listener)?.get(currentTarget ?? target)
}
export const listener = (prototype, properties) =>
freeze(assign(create(prototype), properties))
export const prototype = freeze(assign(create(null), {
listen (target, type, context = null) {
const { capture, once, passive } = this
if (!contexts.has(type)) {
contexts.set(type, new WeakMap())
}
const stores = contexts.get(type)
if (!stores.has(this)) {
stores.set(this, new WeakMap())
}
const store = stores.get(this)
if (store.has(target)) {
throw new Error('Duplicate event listening')
}
store.set(target, context)
target.addEventListener(type, this, { capture, once, passive })
},
forget (target, type) {
const { capture, once, passive } = this
contexts.get(type)?.get(this)?.delete(target)
target.removeEventListener(type, this, { capture, once, passive })
}
}))
import { context, listener, prototype, passive } from './events.js'
export const task = listener(prototype, {
passive,
handleEvent (event) {
const { prop } = context(this, event)
console.log(prop) // 'value'
}
})
import { task } from './task-example.js'
task.listen(element, 'click', {
prop: 'value'
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment