views:

2091

answers:

6

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

+4  A: 

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

eval(settings.functionName + '(' + t.parentNode.id + ')');
Andrew Hare
Wierd - is there a reason this was downvoted?
Andrew Hare
I could downvote it for using eval in an appropriate situation. No need of eval here. Better to find the function as a property of an object. Eval is slow and a bit like using a sledgehammer to swat a fly.
PatrikAkerstrand
Look at Machines answer.
Scott
eval is a common idiom. If you don't like it, you're probably going to hate Javascript in general.IMHO, eval is the correct answer here. Machine's answer is OK if you remove the if-typedef check, but it adds code for no reason. If there's something wrong with the string you're passed, you've got a problem in either scenario.
James Moore
A: 
eval("javascript code");

it is extensively used when dealing with JSON.

+2  A: 

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);
}
Gumbo
+9  A: 
window[settings.functionName](t.parentNode.id);

No need for an eval()

Fabien Ménager
Nice. This is assuming, of course, the function was not declared in a different scope, but even then I would imagine you could do this within that scope...
Paolo Bergantino
It works if the desired function is in the global scope, if not, replace window by the function's scope.
Fabien Ménager
Worked well. Even used less code than the eval function call.
Scott
Nice to see another fella avoiding eval when possible.
PatrikAkerstrand
Eval is evil !!! ;)
Fabien Ménager
+12  A: 

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

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
PatrikAkerstrand
I gave the answer to Machine because of the article. Everyone else was saying that Eval was the best method and then Machine chimed in with the article which def puts the Eval item into perspective and makes me decide not to use it.
Scott
Given the original question, I think the "if(typeof..." code isn't correct. Just call window[settings.functionName](t.parentNode.id). You'll get a TypeError if the function doesn't exist, and that's better than silently swallowing the problem and calling nothing.
James Moore
A: 

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.

Option 1:

If you possibly can, save the function as a function, not as a string, and use it that way 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);

Option 2:

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 lowers the amount of Javascript you have to construct and eval.

Option 3:

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 action = "click"; // Or wherever you got the action name
(itemActions[action])(t.parentNode.id);
Jesse Millikan