82

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?

asked Apr 4, 2010 at 4:19
3
  • 7
    Generally eval is evil ;-) Commented Dec 7, 2017 at 13:27
  • @NurRony Why so? Commented Jul 21, 2022 at 10:39
  • 1
    @ThinkAndCode for performance, Security. Commented Jul 21, 2022 at 11:25

9 Answers 9

93

There's also the Function object.

var adder = new Function("a", "b", "return a + b");
answered Jan 8, 2011 at 16:56
Sign up to request clarification or add additional context in comments.

5 Comments

Nice! This is more along the lines of what I was originally looking for.
JSLint throws a pithy "The Function constructor is eval." I'm still searching for a solution that appeases Crockford.
(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."
Can it be done without using eval() or Function constructor?
@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.
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.

answered Apr 4, 2010 at 4:22

2 Comments

Yep, I don't think it can get much simpler either, but this escaped me for some reason. Thanks.
Use the Function object rather than the eval statement to avoid code smell.
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
56.9k15 gold badges131 silver badges164 bronze badges
answered Jan 23, 2011 at 9:12

1 Comment

This one is actually the most useful if you must pass a function completely as string through the wire.
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());
answered May 19, 2017 at 4:53

2 Comments

best, safest way of dealing with this problem
how is this safer than eval?
6

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();
answered Oct 19, 2016 at 12:50

Comments

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
18.2k18 gold badges94 silver badges102 bronze badges
answered Aug 18, 2015 at 10:54

1 Comment

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].
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
answered Jan 20, 2014 at 20:30

Comments

2

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

answered Feb 21, 2017 at 10:58

Comments

0

I simply created this function and used it

var parseFunction = (stringFunction_)=>{ 
eval('var tempFunction = ' + stringFunction_); 
return tempFunction;
}

then can get function from it

var func = parseFunction('(a,b) =>{return a + b;}');
func(2,2) 
//it will return 4
answered Nov 29, 2023 at 22:07

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.