How to turn a String into a JavaScript function call? [duplicate]


I got a string like:

settings.functionName + '(' + t.parentNode.id + ')';

that I want to translate into a function call like so:

clickedOnItem(IdofParent);

This of course will have to be done in JavaScript. When I do an alert on settings.functionName + '(' + t.parentNode.id + ')'; it seems to get everything correct. I just need to call the function that it would translate into.

Legend:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent

Seeing as I hate eval, and I am not alone:

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

Edit: In reply to @Mahan's comment: In this particular case, settings.functionName would be "clickedOnItem". This would, at runtime translate var fn = window[settings.functionName]; into var fn = window["clickedOnItem"], which would obtain a reference to function clickedOnItem (nodeId) {}. Once we have a reference to a function inside a variable, we can call this function by "calling the variable", i.e. fn(t.parentNode.id), which equals clickedOnItem(t.parentNode.id), which was what the OP wanted.

More full example:

/* Somewhere: */
window.settings = {
  /* [..] Other settings */
  functionName: 'clickedOnItem'
  /* , [..] More settings */
};

/* Later */
function clickedOnItem (nodeId) {
  /* Some cool event handling code here */
}

/* Even later */
var fn = window[settings.functionName]; 
/* note that settings.functionName could also be written
   as window.settings.functionName. In this case, we use the fact that window
   is the implied scope of global variables. */
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

window[settings.functionName](t.parentNode.id);

No need for an eval()


Here is a more generic way to do the same, while supporting scopes :

// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
    var scope = window;
    var scopeSplit = string.split('.');
    for (i = 0; i < scopeSplit.length - 1; i++)
    {
        scope = scope[scopeSplit[i]];

        if (scope == undefined) return;
    }

    return scope[scopeSplit[scopeSplit.length - 1]];
}

Hope it can help some people out.


JavaScript has an eval function that evaluates a string and executes it as code:

eval(settings.functionName + '(' + t.parentNode.id + ')');

eval() is the function you need to do that, but I'd advise trying one of these things to minimize the use of eval. Hopefully one of them will make sense to you.

Store the function

Store the function as a function, not as a string, and use it as a function later. Where you actually store the function is up to you.

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);

or

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);

Store function name

Even if you have to store the function name as a string, you can minimize complexity by doing

(eval(settings.functionName))(t.parentNode.id);

which minimizes the amount of Javascript you have to construct and eval.

Dictionary of handlers

Put all of the action functions you might need into an object, and call them dictionary-style using the string.

// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };

// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);

(Minor note: If instead here you used syntax itemActions[actionName](t.parentNode.id); then the function would be called as a method of itemActions.)


While I like the first answer and I hate eval, I'd like to add that there's another way (similar to eval) so if you can go around it and not use it, you better do. But in some cases you may want to call some javascript code before or after some ajax call and if you have this code in a custom attribute instead of ajax you could use this:

    var executeBefore = $(el).attr("data-execute-before-ajax");
    if (executeBefore != "") {
        var fn = new Function(executeBefore);
        fn();
    }

Or eventually store this in a function cache if you may need to call it multiple times.

Again - don't use eval or this method if you have another way to do that.


If settings.functionName is already a function, you could do this:

settings.functionName(t.parentNode.id);

Otherwise this should also work if settings.functionName is just the name of the function:

if (typeof window[settings.functionName] == "function") {
    window[settings.functionName](t.parentNode.id);
}

I wanted to be able to take a function name as a string, call it, AND pass an argument to the function. I couldn't get the selected answer for this question to do that, but this answer explained it exactly, and here is a short demo.

function test_function(argument)    {
    alert('This function ' + argument); 
}

functionName = 'test_function';

window[functionName]('works!');

This also works with multiple arguments.


This took me a while to figure out, as the conventional window['someFunctionName']() did not work for me at first. The names of my functions were being pulled as an AJAX response from a database. Also, for whatever reason, my functions were declared outside of the scope of the window, so in order to fix this I had to rewrite the functions I was calling from

function someFunctionName() {}

to

window.someFunctionName = function() {}

and from there I could call window['someFunctionName']() with ease. I hope this helps someone!


I prefer to use something like this:

window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);

Based on Nicolas Gauthier answer:

var strng = 'someobj.someCallback';
var data = 'someData';

var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
   //We maybe can check typeof and break the bucle if typeof != function
   func = func[funcSplit[i]];
}
func(data);

In javascript that uses the CommonJS spec, like node.js for instance you can do what I show below. Which is pretty handy for accessing a variable by a string even if its not defined on the window object. If there is a class named MyClass, defined within a CommonJS module named MyClass.js

// MyClass.js
var MyClass = function() {
    // I do stuff in here. Probably return an object
    return {
       foo: "bar"
    }
}

module.exports = MyClass;

You can then do this nice bit o witchcraft from another file called MyOtherFile.js

// MyOtherFile.js

var myString = "MyClass";

var MyClass = require('./' + myString);
var obj = new MyClass();

console.log(obj.foo); // returns "bar"

One more reason why CommonJS is such a pleasure.


eval("javascript code");

it is extensively used when dealing with JSON.