Calling a JavaScript function named in a variable

256,940

Solution 1

I'd avoid eval.

To solve this problem, you should know these things about JavaScript.

  1. Functions are first-class objects, so they can be properties of an object (in which case they are called methods) or even elements of arrays.
  2. If you aren't choosing the object a function belongs to, it belongs to the global scope. In the browser, that means you're hanging it on the object named "window," which is where globals live.
  3. Arrays and objects are intimately related. (Rumor is they might even be the result of incest!) You can often substitute using a dot . rather than square brackets [], or vice versa.

Your problem is a result of considering the dot manner of reference rather than the square bracket manner.

So, why not something like,

window["functionName"]();

That's assuming your function lives in the global space. If you've namespaced, then:

myNameSpace["functionName"]();

Avoid eval, and avoid passing a string in to setTimeout and setInterval. I write a lot of JS, and I NEVER need eval. "Needing" eval comes from not knowing the language deeply enough. You need to learn about scoping, context, and syntax. If you're ever stuck with an eval, just ask--you'll learn quickly.

Solution 2

If it´s in the global scope it´s better to use:

function foo()
{
    alert('foo');
}

var a = 'foo';
window[a]();

than eval(). Because eval() is evaaaaaal.

Exactly like Nosredna said 40 seconds before me that is >.<

Solution 3

Definitely avoid using eval to do something like this, or you will open yourself to XSS (Cross-Site Scripting) vulnerabilities.

For example, if you were to use the eval solutions proposed here, a nefarious user could send a link to their victim that looked like this:

http://yoursite.com/foo.html?func=function(){alert('Im%20In%20Teh%20Codez');}

And their javascript, not yours, would get executed. This code could do something far worse than just pop up an alert of course; it could steal cookies, send requests to your application, etc.

So, make sure you never eval untrusted code that comes in from user input (and anything on the query string id considered user input). You could take user input as a key that will point to your function, but make sure that you don't execute anything if the string given doesn't match a key in your object. For example:

// set up the possible functions:
var myFuncs = {
  func1: function () { alert('Function 1'); },
  func2: function () { alert('Function 2'); },
  func3: function () { alert('Function 3'); },
  func4: function () { alert('Function 4'); },
  func5: function () { alert('Function 5'); }
};
// execute the one specified in the 'funcToRun' variable:
myFuncs[funcToRun]();

This will fail if the funcToRun variable doesn't point to anything in the myFuncs object, but it won't execute any code.

Solution 4

This is kinda ugly, but its the first thing that popped in my head. This also should allow you to pass in arguments:

eval('var myfunc = ' + variable);  myfunc(args, ...);

If you don't need to pass in arguments this might be simpler.

eval(variable + '();');

Standard dry-code warning applies.

Share:
256,940

Related videos on Youtube

Matt W
Author by

Matt W

I write code for fun and profit. Sometimes I blog about it. Not enough time for either. At work I break websites. At home I break physics based mobile games. "No code more than 8 lines ever worked as intended first time." - My Dad.

Updated on June 29, 2020

Comments

  • Matt W
    Matt W almost 4 years

    I have a JavaScript variable which contains the name of a JavaScript function. This function exists on the page by having been loaded in and placed using $.ajax, etc.

    Can anyone tell me how I would call the javascript function named in the variable, please?

    The name of the function is in a variable because the URL used to load the page fragment (which gets inserted into the current page) contains the name of the function to call.

    I am open to other suggestions on how to implement this solution.

    • Crescent Fresh
      Crescent Fresh over 14 years
      This has been asked about 18 times before on SO. Please search.
    • arkap
      arkap over 14 years
      sounds more like a callback... is it?
    • Dominic Rodger
      Dominic Rodger over 14 years
      @Crescent Fresh, FWIW, I don't see anything in the related sidebar that looks relevant.
    • Crescent Fresh
      Crescent Fresh over 14 years
      @Dominic: fair enough. Try instead google.com/…
    • Nosredna
      Nosredna over 14 years
      Kinda makes you wish StackOverflow used Google as its search.
    • I try so hard but I cry harder
      I try so hard but I cry harder over 2 years
      @CrescentFresh Sometimes you have to be very specific in your searches to have the question come up in google though. I would say a bit too specific.
  • Quentin
    Quentin over 14 years
    … and if you are going to do something like this, you should probably have your functions defined as members of an object.
  • liran
    liran over 14 years
    I agree, eval() should be avoided in this case, to avoid XSS issues.
  • Nosredna
    Nosredna over 14 years
    @David Dorwald: Exactly. Namespacing is preferable. You don't want some function name coming in off an ajax call to clobber something else.
  • anddoutoi
    anddoutoi over 14 years
    Yeah, upvoted your answer in all fairness of you beating me ;)
  • Nosredna
    Nosredna over 14 years
    Upvoted yours because I'm a hell of a nice guy.
  • Matt W
    Matt W over 14 years
    I agree - there is a lot I need to learn about javascript, but the necessary evil is that I do need to use it now. I seem to remember something about js executed in eval only exists (including it's timers, etc) for the time the eval is executing - causing even more problems. Is this true. Anyway, I finally solved the problem by removing the need to dynamically call functions (phew!) I wanted to originally because it's my own pages only that would contain the javascript, not external pages.
  • gorn
    gorn over 10 years
    myNameSpace["functionName"](); .. This is great, but can I pass in a parameter? Like so: myNameSpace["functionName"](param);
  • rob
    rob over 9 years
    @gom took me 12 seconds to try it in the browsers JavaScript console function myfunc(s) { console.log(':'+s);} window["myfunc"]('message');
  • nirmal
    nirmal almost 9 years
    it was good and solved mine issue, but is it fine to use eval ?
  • a coder
    a coder about 8 years
    Can you fiddle this with a couple buttons?
  • avalanche1
    avalanche1 almost 8 years
    Why wouldn't it be safe? Eval is evil only when you pass it user input. Like having an eval func server-side which accepts client data as argument
  • cepatt
    cepatt over 7 years
    Thank you. While possibly not exactly what the user needed, this is exactly what I needed. I forgot my () when calling my function.
  • THpubs
    THpubs over 7 years
    Best for node apps! Thanks!
  • geoidesic
    geoidesic about 4 years
    What if the function is imported?