What exactly is the parameter e (event) and why pass it to JavaScript functions?

Viewed 102802

Well, when I learned JavaScript, all the books and Internet articles I read showed code passing a parameter e to functions that handle JavaScript events, such as the code block below:

function myEvent(e) {
    var evtType = e.type
    alert(evtType)
    // displays click, or whatever the event type was
}

I've always accepted that as being the way it is, but now I have some questions (this is very confusing to me):

  1. Where does this e come from? When I look at the entire JavaScript file, e does not seem to exist at all.
  2. Why pass this parameter e to functions? Will functions stop working if I do not pass e to them?
  3. Consider the code block below. There is an event variable (e) passed to an anonymous inner function. Let's say I want to use an event object outside of the anonymous function (maybe in a line above/below the element.onkeypress line). How can I do this?

    element.onkeypress = function(e) {
        if(e.keyCode) {
            element.keyCode = e.keyCode;
        } else {
            element.keyCode = e.charCode;
        }
    };
    
5 Answers

I will try my best to explain in the most abstract way possible. The real implementation is probably a lot more complex. Therefore, the names that I am about to use are hypothetical but they do serve a good purpose for explaining things, I hope ;)


Every node in the browser is an implementation of EventEmitter class. This class maintains an object events that contains key:value pairs of eventType (the key) : an Array containing listener functions (the value).

The two functions defined in the EventEmitter class are addEventListener and fire.

class EventEmitter {
  constructor(id) {
    this.events = {};
    this.id = id;
  }

  addEventListener(eventType, listener) {
    if (!this.events[eventType]) {
      this.events[eventType] = [];
    }

    this.events[eventType].push(listener);
  }

  fire(eventType, eventProperties) {
    if (this.events[eventType]) {
      this.events[eventType].forEach(listener => listener(eventProperties));
    }
  }
}

addEventListener is used by the programmer to register their desired listener functions to be fired upon the execution of their desired eventType.

Note that for each distinct eventType, there is a distinct array. This array can hold multiple listener functions for the same eventType.


fire is invoked by the browser in response to user interactions. The browser knows what kind of interaction has been performed and on what node it has been performed. It uses that knowledge to invoke fire on the appropriate node with the appropriate parameters which are eventType and eventProperties.

fire loops through the array associated with the specific eventType. Going through the array, it invokes every listener function inside the array while passing eventProperties to it.

This is how the listener functions, registered only with the particular eventType, are invoked once fire is called.


Following is a demonstration. There are 3 Actors in this demonstration. Programmer, Browser and the User.

let button = document.getElementById("myButton"); // Done by the Programmer
let button = new EventEmitter("myButton"); // Done by the Browser somewhere in the background. 


button.addEventListener("click", () =>
  console.log("This is one of the listeners for the click event. But it DOES NOT need the event details.")
); // Done By the Programmer


button.addEventListener("click", e => {
  console.log(
    "This is another listener for the click event! However this DOES need the event details."
  );
  console.log(e);
}); // Done By the Programmer


//User clicks the button


button.fire("click", {
  type: "click",
  clientX: 47,
  clientY: 18,
  bubbles: true,
  manyOthers: "etc"
}); // Done By the Browser in the background

After the user clicks on button, Browser invokes fire on button passing "click" as an eventType and the object holding eventProperties. This causes all the registered listener functions under "click" eventType to be invoked.

As you can see, the Browser ALWAYS puts eventProperties on fire. As a programmer, you may or may not use those properties in your listener functions.


Some answers that I found helpful on stackoveflow:

Where is an event registered with addEventListener stored?

Where are Javascript event handlers stored?

Related