Given a string describing a Javascript function, convert it to a Javascript function
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?
There's also the Function object.
var adder = new Function("a", "b", "return a + b");
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.
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.
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());