How to turn a String into a JavaScript function call?

JavascriptFunction

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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);
}

Solution 2 - Javascript

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

No need for an eval()

Solution 3 - Javascript

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.

Solution 4 - Javascript

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

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

Solution 5 - Javascript

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.)

Solution 6 - Javascript

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.

Solution 7 - Javascript

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][1] 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. [1]: https://stackoverflow.com/questions/5818313/javascript-equivalent-of-phps-call-user-func

Solution 8 - Javascript

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);
}

Solution 9 - Javascript

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!

Solution 10 - Javascript

I prefer to use something like this:

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

Solution 11 - Javascript

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.

Solution 12 - Javascript

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);

Solution 13 - Javascript

eval("javascript code");

it is extensively used when dealing with http://www.json.org/js.html">JSON</a>;.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSpoiledTechie.comView Question on Stackoverflow
Solution 1 - JavascriptPatrikAkerstrandView Answer on Stackoverflow
Solution 2 - JavascriptFabien MénagerView Answer on Stackoverflow
Solution 3 - JavascriptNGauthierView Answer on Stackoverflow
Solution 4 - JavascriptAndrew HareView Answer on Stackoverflow
Solution 5 - JavascriptJesse MillikanView Answer on Stackoverflow
Solution 6 - JavascriptnsimeonovView Answer on Stackoverflow
Solution 7 - JavascriptB Rad CView Answer on Stackoverflow
Solution 8 - JavascriptGumboView Answer on Stackoverflow
Solution 9 - Javascriptuser866256View Answer on Stackoverflow
Solution 10 - JavascriptTom JohnsonView Answer on Stackoverflow
Solution 11 - JavascriptnackjicholsonView Answer on Stackoverflow
Solution 12 - JavascriptMarcos Fernandez RamosView Answer on Stackoverflow
Solution 13 - JavascriptanonView Answer on Stackoverflow