Is there a way to create a function from a string with javascript?
Asked Answered
S

10

143

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.

Sensualist answered 4/10, 2011 at 15:10 Comment(0)
C
120

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

Cayla answered 18/1, 2015 at 15:16 Comment(2)
@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.Cayla
@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.Beggarly
B
204

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'
Burglar answered 4/10, 2011 at 15:16 Comment(5)
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)();Coroner
I think this probably should be the accepted answer. It's much safer than eval().Pete
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');");Toothbrush
@RyanGriggs In your case you do not need the "eval" functionality so it is better written as element.onclick = function() { alert("test"); }.Burglar
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.Toothbrush
C
120

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

Cayla answered 18/1, 2015 at 15:16 Comment(2)
@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.Cayla
@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.Beggarly
H
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.

Howell answered 4/10, 2011 at 15:13 Comment(3)
i knew that the function was declared, but couldnt guess to call function name. Thanks alot.Sensualist
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 stringTurnspit
what if you don't have the name of function since it came from a database record?Teleutospore
I
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

Indeterminacy answered 13/11, 2014 at 20:37 Comment(2)
hi please support arrow function support to this method?Purvey
I'm receiving this error in typescirpt "Property 'parseFunction' does not exist on type 'String'."Unitarian
C
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'
Ce answered 9/12, 2013 at 14:49 Comment(0)
U
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>
Uptake answered 19/1, 2015 at 6:41 Comment(0)
W
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()
Whisenhunt answered 27/1, 2018 at 2:16 Comment(0)
T
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]))
Thebault answered 30/10, 2017 at 1:16 Comment(1)
Thanks. Very interestingIntuitivism
S
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]
Speakeasy answered 5/3, 2022 at 8:2 Comment(0)
K
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

Kay answered 29/11, 2023 at 20:19 Comment(1)
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()"Casta

© 2022 - 2024 — McMap. All rights reserved.