Using javascript objects as a "function store" and calling them dynamically?

Viewed 101

Consider something like this:

const keyAction = {
    a() {
        console.log("You've pressed 'a'");
    },
    b() {
        console.log("You've pressed 'b'");
    },
    c() {
        console.log("You've pressed 'c'");
    }
}

document.addEventListener('keydown', e => keyAction[e.key]());

Is this a bad practice? Are there any reason to not do it this way?

3 Answers

It's a popular practice actually, as some people tend to use objects to simulate namespaces from other languages. I think there's nothing bad with it, as long as you understand the traps that this approach may set. For example you should keep in mind what happens to this when you pass these functions as parameters (look at the example below):

const store = {
    a() {
        this.b();
    },
    b() {
        console.log("It works!");
    }
}

store.a();  // Logs "It works"
setTimeout(store.a, 10) // Error: this.b is not a function

Also, as noted by @Nick Ovchinnikov, in your specific example there is one other pitfall. You should make sure, that whenever a button is pressed, the environment will not try to invoke a function which doesn't exist - otherwise you might encounter an error. So eventually your handler binding should look somewhat like this:

document.addEventListener('keydown', e => {
    if (typeof keyAction[e.key] === 'function') {
        keyAction[e.key]();
    }
});

You have a problem, when you press a key which you haven't handled, you will see Error: keyAction[e.key] is not a function

if (typeof keyAction[e.key] === 'function') {
    return keyAction[e.key]()
}

console.log('You pressed a some button')

Javascript is dynamic language, of course for some kind of cases it's very great. But don't need to abuse, because you could lost control faster, than you can imagine

Using an object as function store is not a bad idea. It's easy to understand, easy to maintain and quick to access (because of the hashmap system). It also makes you able to perform treatment on your data compared to an if/else if/... thing - for example, doing a loop ... ect

Depending on what you are trying to do it can be a good help.

Try to avoid recreating the object every time you call the function tho. Build it once and reuse it.

const keyAction = {
  a: () => {
    console.log("You've pressed 'a'");
  },

  b: () => {
    console.log("You've pressed 'b'");
  },
};

function clickFunc(key) {
  keyAction[key]();
}
.ex {
  background-color: #444444;
  color: white;
  height: 5em;
  width: 5em;
  margin: 1em;
  cursor: pointer;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
}
<div class="ex" onclick="clickFunc('a')">
  A
</div>

<div class="ex" onclick="clickFunc('b')">
  B
</div>

Related