76

Say I've got a Javascript string like the following

var fnStr = "function(){blah1;blah2;blah3; }" ;

(This may be from an expression the user has typed in, duly sanitized, or it may be the result of some symbolic computation. It really doesn't matter).

I want to define fn as if the following line was in my code:

var fn = function(){blah1;blah2;blah3; } ;

How do I do that?

The best I've come up with is the following:

var fn = eval("var f = function(){ return "+fnStr+";}; f() ;") ;

This seems to do the trick, even though it uses the dreaded eval(), and uses a slightly convoluted argument. Can I do better? I.e. either not use eval(), or supply it with a simpler argument?

brainjam
  • 18,863
  • 8
  • 57
  • 82

8 Answers8

89

There's also the Function object.

var adder = new Function("a", "b", "return a + b");
goat
  • 31,486
  • 7
  • 73
  • 96
  • 1
    Nice! This is more along the lines of what I was originally looking for. – brainjam Jan 08 '11 at 19:10
  • 4
    JSLint throws a pithy "The Function constructor is eval." I'm still searching for a solution that appeases Crockford. – Dom Vinyard Jan 17 '14 at 08:59
  • 14
    **(Difference with eval)** *"Note: Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, **they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called**. This is different from using eval with code for a function expression."* – BeauCielBleu Jun 28 '14 at 08:33
  • Can it be done without using eval() or Function constructor? – Ozil Aug 08 '16 at 11:38
  • 1
    @Ozil No, that doesn't make sense. You need to convert a string representation to a function. That requires the use of something that can evaluate strings into javascript code. Eval/the Function aren't always evil/their threats are gravely overstated. – Foobar Sep 04 '18 at 19:39
40

You can do this:

//in your case: eval("var fn = " + fnStr);
eval("var fn = function(){ blah1;blah2;blah3; }"); 
fn();

Not sure how to get it much simpler, sometimes there's no (better) way around eval(). Here's a quick example of this in action.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
22

Use parentheses.

var fn = eval("(function() {...})");

This technique is also good for transmitting JSON values.

By the way, it's often better to build functions by composing them directly from other functions. If you are using strings, you have to worry about things like unexpected variable capture.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Eric
  • 271
  • 2
  • 6
13

Here's what I use for simple cases:

// an example function
function plus(...args) {
    return args.reduce( (s,v) => s+v, 0 );
}

// function to string
let str = plus.toString();

// string to function
let copy = new Function('return ' + str)();

// tests
console.assert(plus.name == 'plus');
console.assert(copy.name == 'plus');
console.assert(plus.constructor == Function);
console.assert(copy.constructor == Function);
console.assert(plus(1,2,3,4) === copy(1,2,3,4));
console.assert(plus.toString() === copy.toString());
Julian TF
  • 465
  • 5
  • 10
5

You can also insert the string into a script element and then insert the script element into the page.

script_ele = window.document.createElement("script");
script_ele.innerHTML = 'function my_function(){alert("hi!");}';
window.document.body.appendChild(script_ele);
my_function();
user984003
  • 28,050
  • 64
  • 189
  • 285
4

One way:

     var a = 'function f(){ alert(111); } function d(){ alert(222);}';  
     eval(a);
     d();
     

A second more secure way to convert string to a function:

     // function name and parameters to pass
    var fnstring = "runMe";
    var fnparams = ["aaa", "bbbb", "ccc"];
    
    // find object
    var fn = window[fnstring];
    
    // is object a function?
    if (typeof fn === "function") fn.apply(null, fnparams);
    
    
    function runMe(a,b){
      alert(b);
    }

Look at the working code: http://plnkr.co/edit/OiQAVd9DMV2PfK0NG9vk

SherylHohman
  • 16,580
  • 17
  • 88
  • 94
Arthur Tsidkilov
  • 5,401
  • 2
  • 21
  • 18
  • This only works for top level functions. `fnstring = 'alert'` will work. `fnstring = 'console.log'` will not. Namespaced functions need to use the namespace instead of the global `window`. For example, `fnstring = 'log'` -> `fn = console[fnstring]`. – OXiGEN Nov 17 '22 at 03:25
3

The Function constructor creates a new Function object. In JavaScript every function is actually a Function object.

// Create a function that takes two arguments and returns the sum of those arguments
var fun = new Function("a", "b", "return a + b");
// Call the function
fun(2, 6);
Output: 8
SK.
  • 4,174
  • 4
  • 30
  • 48
3

You can call Parse your string as javascript fuction

  1. function getDate(){alert('done')} // suppose this is your defined function

to call above function getDate() is this in string format like 'getDate()'

  1. var callFunc=new Function('getDate()') //Parse and register your function

  2. callFunc() // Call the function

Satish Kumar sonker
  • 1,250
  • 8
  • 15