9

So, I have had this curiosity for quite a while now. I want to know, how addEventListener works behind the scenes. I know what it does but I am just not able to get my head around how it does it.

I have checked many links and resources and this is the one that was closest to what I was looking for but still no success.

To clarify on what I am really looking for, I want to know how can one create his own addEventListener function that would take the first argument as the event name and the second argument as the callback that would accept the eventArgs argument.

  • 2
    `addEventListener` is the API provided by the browser to listen for DOM events. As the event processing and handling is part of the browsers DOM Model and its internals are not accessible from the JavaScript side (at least not for the common browsers), there is no way to implement your own `addEventListener` without using `addEventListener` at some point. – t.niese Aug 26 '19 at 11:53
  • Internally, how does it know when, lets say, a mouse click occurs, then this function should be called? It should have some kind of `listener` thread that keeps listening for any event. –  Aug 26 '19 at 11:58
  • How the browser vendor solves that task in detail is highly implementation-dependent. – t.niese Aug 26 '19 at 12:01
  • 4
    A pity that such an interesting question is on hold. The thing is that JS is compiled by a compiler which is different in each browser. So, the magic actually happens in compiler's inner C or C++ code. You may check the open code of Chromium compiler [here](https://github.com/chromium/chromium/search?l=C%2B%2B&q=addEventListener&type=). – Igor Bykov Aug 26 '19 at 12:24
  • @IgorBykov It's interesting but as it is, there is no answer that can be given, it would be different if it had a specific brower mentioned like chromium and was about its C++ code, but it's not. And even if it was about creating custom events, it could be closed as a dupe of for example [this question](https://stackoverflow.com/questions/9671995/javascript-custom-event-listener) – Kaddath Aug 26 '19 at 14:33

4 Answers4

2

This would be simple example of event dispatching system

class BusEvent {
    eventName = null;
    callbacks = [];

    constructor(eventName) {
        this.eventName = eventName;
    }

    register(callback) {
        this.callbacks.push(callback);
    }

    unregister(callback) {
        const index = this.callbacks.indexOf(callback);
        if (index > -1) {
            this.callbacks.splice(index, 1);
        }
    }

    execute(data) {
        const callbacks = this.callbacks.slice(0);
        callbacks.forEach((callback) => {
            callback(data);
        });
    }
}

class MessageBus {
    constructor() {
        this.events = {};
    }

    dispatch(eventName, data) {
        const event = this.events[eventName];
        if (event) {
            event.execute(data);
        }
    }

    on(eventName, callback) {
        let event = this.events[eventName];
        if (!event) {
            event = new BusEvent(eventName);
            this.events[eventName] = event;
        }
        event.register(callback);
    }

    off(eventName, callback) {
        const event = this.events[eventName];
        if (event && event.callbacks.indexOf(callback) > -1) {
            event.unregister(callback);
            if (event.callbacks.length === 0) {
                delete this.events[eventName];
            }
        }
    }
}

Usage:

const messageBus = new MessageBus();
messageBus.on('ReceiveData', (data) => {
    console.log(data);
})

messageBus.dispatch('ReceiveData', { name: 'Ted' });
// console logs { name: 'Ted' }
zhuber
  • 5,364
  • 3
  • 30
  • 63
2

As far as I know JS has kind of a Observer, which is a design pattern from GoF (Gang of Four), you can read more here. The Observer will keep waiting for the state change, and then when it's changed the callback will be called notifying all the objects. The UML bellow will give you an idea of how it works.

enter image description here

So, I do think JS works on that way, but instead of all objects be the same each one will have a custom callback, or more than one callback.I'm not pretty sure about that, but should works that way. I didn't found anything online, but this Reddit topic talks about it

Esdras Xavier
  • 867
  • 1
  • 7
  • 18
  • 1
    Thanks for this. It clarified many of my doubts if not all. –  Aug 26 '19 at 12:21
  • 1
    No problem, glad for help. But as I said, I'm not pretty sure if JS event listener works on that way, but should be something similar. – Esdras Xavier Aug 26 '19 at 12:24
0

If you want to add a custom event to the DOM, I don't think that is possible. At least i'm not aware of any specification to support that. There is the custom element spec that allows you to create your own web components. In doing that you can check which events could be fired. However, you can do the same concept outside of the DOM:

var callbacks = [];
function addToEventListener(callback) {
    callbacks.push(callback);
}

function triggerMyEvent(payload) {
    callbacks.forEach(function(cb){
        cb(payload);
    });
}

addToEventListener(function(p){
    console.log(p);
});

triggerMyEvent({testValue:true});

Note: the above uses globals, which isn't a good practice. I would recommend against that, but for brevity of this post, I chose to use globals. The ideas are the same.

pgreen2
  • 3,601
  • 3
  • 32
  • 59
  • 2
    You can create custom events using, [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) and trigger them on any DOM element you want. – t.niese Aug 26 '19 at 11:59
-1

addEventLisner bind the handle with html DOM node. It takes the event that to be attach and one callback function.