Nick Black
Nick Black

Reputation: 37

How do I call a function through a string matching the name and execute it?

I am grabbing the innerHTML off of a clicked list item in an unordered list. I save this string to a variable and I want to call a function with the same name as this variable.

I've done some research and found some different articles but none of it worked. eval was referenced as a haphazard way of doing it, but I could not get that to work. Also another was using Window but the code didn't work for me.

How can I call that variable as a function. i.e. clickedName()

right now calling clickedName() gives the error

Uncaught TypeError: clickedName is not a function
    at HTMLUListElement.<anonymous> 

Here is the code I am using:

index.html

<div id="myDiv">test</div>

    <ul id="parent-list">
        <li>Cats</li>
        <li>Dogs</li>
    </ul>

script.js

document.getElementById("parent-list").addEventListener("click", function(e) {
    if (e.target && e.target.nodeName == "LI") {
        // console.log(e.target.innerHTML + " was clicked");
        // call function respective to element clicked
        let clickedName = e.target.innerHTML;
        console.log(clickedName);

    }
 });


function cat() {
    const myElem = document.createElement("div");
    let myString = `<div>Meow, Meow, Meow</div>`;

    myElem.innerHTML = myString;

    // put on page
    document.getElementById("myDiv").append(myElem);
} // catClick

Upvotes: 1

Views: 275

Answers (2)

IceMetalPunk
IceMetalPunk

Reputation: 5566

One way that I would not recommend is to know that functions declared "normally" (as in, with function fName() {} in global scope) are part of the window object, so doFunction() is the same as window.doFunction(). Thus you can do this:

window[clickedName]();

But that means users can input the name of ANY function on the global scope to run it, which isn't great. Instead, I'd suggest encapsulating the functions you want to be able to run this way into a specific object holding just those methods; then you can call from that:

const allowedFunctions = {
    firstAllowed: function() { /* ... */ },
    someOtherFunction: function() { /* ... */ }
};
// ...then later, to call it...
if (allowedFunctions[clickedName]) { allowedFunctions[clickedName](); }

Upvotes: 2

Violet Rosenzweig
Violet Rosenzweig

Reputation: 665

If the function is declared in the current scope, this[clickedName]() should work. This is because the function is a method on the this object, and as such should be accessible through it. However, if the function is a part of another object, say anObject, you can just do anObject[clickedName]()

Upvotes: 2

Related Questions