Riffing on @SuperNova's answer, here's an approach using ES6 classes that keeps the context for this
correct in your callback:
class Mouse {_x000D_
constructor() {_x000D_
this.x = 0;_x000D_
this.y = 0;_x000D_
this.callbacks = {_x000D_
mouseenter: [],_x000D_
mousemove: [],_x000D_
};_x000D_
}_x000D_
_x000D_
get xPos() {_x000D_
return this.x;_x000D_
}_x000D_
_x000D_
get yPos() {_x000D_
return this.y;_x000D_
}_x000D_
_x000D_
get position() {_x000D_
return `${this.x},${this.y}`;_x000D_
}_x000D_
_x000D_
addListener(type, callback) {_x000D_
document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct_x000D_
this.callbacks[type].push(callback);_x000D_
}_x000D_
_x000D_
// `handleEvent` is part of the browser's `EventListener` API._x000D_
// https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent_x000D_
handleEvent(event) {_x000D_
const isMousemove = event.type === 'mousemove';_x000D_
const isMouseenter = event.type === 'mouseenter';_x000D_
_x000D_
if (isMousemove || isMouseenter) {_x000D_
this.x = event.pageX;_x000D_
this.y = event.pageY;_x000D_
}_x000D_
_x000D_
this.callbacks[event.type].forEach((callback) => {_x000D_
callback();_x000D_
});_x000D_
}_x000D_
}_x000D_
_x000D_
const mouse = new Mouse();_x000D_
_x000D_
mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));_x000D_
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));_x000D_
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));
_x000D_