146

For example;

var s = "function test(){
  alert(1);
}";

var fnc = aMethod(s);

If this is the string, I want a function that's called fnc. And fnc(); pops alert screen.

eval("alert(1);") doesnt solve my problem.

10 Answers 10

207

A better way to create a function from a string is by using Function:

var fn = Function("alert('hello there')");
fn();

This has as advantage / disadvantage that variables in the current scope (if not global) do not apply to the newly constructed function.

Passing arguments is possible too:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'
Sign up to request clarification or add additional context in comments.

5 Comments

Agree, with Function you don't pollute the local scope and this is why eval makes optimization so hard for engines... With the OP example, I would: var fnc = Function('return '+s)();
I think this probably should be the accepted answer. It's much safer than eval().
You, my friend, deserve many upvotes. This has the advantage of creating a function object which can be assigned to events, etc. For example: element.onclick = Function("alert('test');");
@RyanGriggs In your case you do not need the "eval" functionality so it is better written as element.onclick = function() { alert("test"); }.
You are correct from my example. However, if you wanted to assign arbitrary functions stored in strings, your method is perfect. This is what I'm actually trying to do. I have multiple functions stored in string variables, and want to assign one to an onclick action.
123

I added a jsperf test for 4 different ways to create a function from string :

  • Using RegExp with Function class

    var func = "function (a, b) { return a + b; }".parseFunction();

  • Using Function class with "return"

    var func = new Function("return " + "function (a, b) { return a + b; }")();

  • Using official Function constructor

    var func = new Function("a", "b", "return a + b;");

  • Using Eval

    eval("var func = function (a, b) { return a + b; };");

http://jsben.ch/D2xTG

2 result samples: enter image description here enter image description here

2 Comments

@KthProg Chill down ;). It's not always bad, like this situation, the jsperf is down at the moment, luckily I added the result screenshots before it was down, when I got the comment from Bulk.
@KthProg FYI this was a canned response generated by the moderation system :) it pops up in a queue and we check for predetermined problems, one of which this comment is designed to fix. It's not a hard and fast rule, and you'll notice the comment is in the form of a suggestion not a command.
40

You're pretty close.

//Create string representation of function
var s = "function test(){  alert(1); }";

//"Register" the function
eval(s);

//Call the function
test();

Here's a working fiddle.

3 Comments

i knew that the function was declared, but couldnt guess to call function name. Thanks alot.
Obligatory eval warning to future searchers: eval can open loopholes for hackers: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… but if you know its dangers and can avoid them, then this is a nice simple way to create a function from a string
what if you don't have the name of function since it came from a database record?
16

Yes, using Function is a great solution but we can go a bit further and prepare universal parser that parse string and convert it to real JavaScript function...

if (typeof String.prototype.parseFunction != 'function') {
    String.prototype.parseFunction = function () {
        var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
        var match = funcReg.exec(this.replace(/\n/g, ' '));

        if(match) {
            return new Function(match[1].split(','), match[2]);
        }

        return null;
    };
}

examples of usage:

var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));

func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();

here is jsfiddle

2 Comments

hi please support arrow function support to this method?
I'm receiving this error in typescirpt "Property 'parseFunction' does not exist on type 'String'."
14

Dynamic function names in JavaScript

Using Function

var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'

Source: http://marcosc.com/2012/03/dynamic-function-names-in-javascript/

Using eval

var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'

Using sjsClass

https://github.com/reduardo7/sjsClass

Example

Class.extend('newClassName', {
    __constructor: function() {
        // ...
    }
});

var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'

Comments

8

This technique may be ultimately equivalent to the eval method, but I wanted to add it, as it might be useful for some.

var newCode = document.createElement("script");

newCode.text = "function newFun( a, b ) { return a + b; }";

document.body.appendChild( newCode );

This is functionally like adding this <script> element to the end of your document, e.g.:

...

<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>

</body>
</html>

Comments

5

Use the new Function() with a return inside and execute it immediately.

var s = `function test(){
  alert(1);
}`;

var new_fn = new Function("return " + s)()
console.log(new_fn)
new_fn()

Comments

2

An example with dynamic arguments:

let args = {a:1, b:2}
  , fnString = 'return a + b;';

let fn = Function.apply(Function, Object.keys(args).concat(fnString));

let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))

Comments

0

If you have a function expression that is in string form and you want to make it a function, then you need to include a return statement in the string you pass to new Function.

const strFn = "const sum = (a, b) => a + b"

const newFn = new Function(`${strFn}; return sum`)();

console.log(newFn(2, 3)) // 5

If you don't execute immediately, you can use the function.call method to execute. Remember the first argument it takes is the this value

const newFn = new Function('const arrMultiplier = (arr) => arr.map(num => num * 2); return arrMultiplier')
console.log(newFn.call({}).call({}, [6, 4, 1, 0])); // [12, 8, 2, 0]

Comments

0

you should simply use eval and not use function key word and function name that will be like this

var s = `()=>{
   alert(1);
}`;

var fnc = eval(s);

eval function returns the function into fnc

1 Comment

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… : "Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval()"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.