How to Call a JavaScript Function From a String Without Using eval

Contributing Editor

eval is evil in JavaScript! The MDN eval page states:

Obsolete
This feature is obsolete. Although it is still supported by browsers, its usage is discouraged in new projects. Try to avoid using it.

eval executes a string containing code, e.g.

eval("var x = 'Hello from eval!';");
console.log(x);

eval raises several issues:

  1. Security: your string can be injected with other commands by third-party scripts or user input.
  2. Debugging: it’s difficult to debug errors — you have no line numbers or obvious points of failure.
  3. Optimization: the JavaScript interpreter cannot necessarily pre-compile the code because it could change. While interpreters have become increasingly efficient, it’ll almost certainly run slower than native code.

Unfortunately, eval is very powerful and it’s easy for less experienced developers to overuse the command.

Despite the warnings, eval still works — even in Strict Mode — but you can normally avoid it. In the past it was primarily used for de-serializing JSON strings but we now have the safer JSON.parse method.

However, what if we have a function name in a string, e.g.

// function we want to run
var fnstring = "runMe";

function runMe() {
	// do stuff
}

How do we execute the runMe() function without using eval? I recently encountered this situation when using the HTML5 History API; the pushState method won’t permit you to store a direct reference to a function so you need to define its name as a string. You could also face similar challenges using Web Workers or any other API where objects are serialized.

The simplest and safest execution-without-eval solution is a range of conditions, e.g.

// function we want to run
var fnstring = "runMe";

switch (fnstring) {
	case "functionX": functionX(); break;
	case "functionY": functionY(); break;
	case "functionZ": functionZ(); break;
	case "runMe": runMe(); break;
}

It’s safe, but fairly inefficient and painful to write if you have dozens of possible function calls.

A better solution is to use the window object which references the current window and all items within it. We can check whether fnstring is available as an object within window and run it if it’s a function, e.g.

// function we want to run
var fnstring = "runMe";

// find object
var fn = window[fnstring];

// is object a function?
if (typeof fn === "function") fn();

You can perform other checks if necessary to ensure the function has an expected name.

What if the function we want to call has parameters — perhaps stored in an array? No problem; we simply use the apply method:

// function name and parameters to pass
var fnstring = "runMe";
var fnparams = [1, 2, 3];

// find object
var fn = window[fnstring];

// is object a function?
if (typeof fn === "function") fn.apply(null, fnparams);

So that’s another reason to stop using eval. As a bonus, this solution is safer, less error prone, easier to debug and will normally execute faster. I hope it helps.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Sander Belen

    You can do the same with operators!

    var compare = {
    ‘==’ : function(a, b) { return a == b },
    ‘< ' : function(a, b) { return a < b },
    '>‘ : function(a, b) { return a > b },
    ‘< =' : function(a, b) { return a <= b },
    '>=’ : function(a, b) { return a >= b }
    };

  • Anonymous
  • Anonymous

    if(‘$’ in window && typeof window['$'] == ‘function’) window['$'](document);

  • Anonymous

    I thought it was about how to evaluate a function body without using eval. We can pass complete string to Function constructor along with parameters array. and then call that method like new Function(“console.log(‘String function’)”)(). But this is another good thing to know. I was not aware of this trick. Great job thanks.

  • Njanga

    Great article.

  • Anonymous

    One could also use:
    setTimeout(“runMe”,0);

    • jabez

      cool method

  • Jose

    Great article, servers in general including with parameters, easy to convert existing code using ‘eval’ to this one with the window object.
    Thank you Craig.

  • markus

    Thank you for contributing this! Great Trick!

  • mrhoo

    The global eval is not deprecated, but using eval as a method of an Object is.

  • Sajjad

    or if you are trying to call a function of an object
    fn.apply(object, fnparams);