Elegantly detecting the presence (and type) or absence of an Event Object inside a callback function

Viewed 35

I have a function which I intend to fire on several different Events.

Importantly, the function may also be invoked directly.

But I need the function to know which event it is being fired by... or whether it is being invoked directly.

I realised I could (somehow) harness the Event Object and use something like:

const myFunction = (e) => {

  if ((e !== undefined) && (e.hasOwnProperty('type')) {

    switch (e.type) {

      case ('click'):      console.log('Click Event');       break;
      case ('mouseover'):  console.log('Mouseover Event');   break;
    }
  }

  else {

    console.log('Separately invoked');
  }
}

This isn't terrible, but it's more verbose than I want it to be and I'm not too keen on trying to verify the Event Object by checking if e is both not undefined and has a particular property... this all seems a very roundabout approach to verifying the presence of an Event Object.

Is there a better way to check for the [presence and type] or [absence] of an Event Object?

2 Answers

You can use optional chaining and nullish coalescing to get the type or "direct" for a direct call:

const myFunction = (e) => {
    switch (e?.type ?? "direct") {
        case "click":
            console.log("Click Event");
            break;
        case "mouseover":
            console.log("Mouseover Event");
            break;
        case "direct":
            console.log("Separately invoked");
            break;
        default:
            console.log("Other");
            break;
    }
};

With your inline case format:

const myFunction = (e) => {
    switch (e?.type ?? "direct") {
        case "click":     console.log("Click Event");        break;
        case "mouseover": console.log("Mouseover Event");    break;
        case "direct":    console.log("Separately invoked"); break;
        default:          console.log("Other");              break;
    }
};

Or without those relatively-new features, logical && and ||:

const myFunction = (e) => {
    switch ((e && e.type) || "direct") {
        // ...
    }
};

Is there a better way to check for the [presence and type] or [absence] of an Event Object?

It turns out there is.

ES2020 introduces Optional Chaining, using the operator ?. which at any point returns undefined if any property in the chain - or even the parent object - cannot be found.

This means that in any

const myFunction = (e) => { [... CODE HERE... ] }

we may use this:

e?.type

which returns:

  • the EventObject.type, if function parameter e is the Event Object
  • undefined, if function parameter e is an object / data structure lacking the property type
  • undefined, if the function has been invoked without any parameter

Working Example:

const myDiv = document.querySelector('.myDiv');

const myFunction = (e) => {

  switch (e?.type) {

    case ('click') : console.log('Click Event'); break;
    case ('mouseover') : console.log('Mouseover Event'); break;
    default : console.log('Separately invoked');
  }
}

setInterval(myFunction, 3000);

myDiv.addEventListener('mouseover', myFunction, false);
myDiv.addEventListener('click', myFunction, false);
.myDiv {

  width: 100px;
  height: 100px;
  background-color: rgb(255, 0, 0);
}
<div class="myDiv"></div>


Further Reading:

Related