Czy istnieje sposób na utworzenie funkcji z ciągu znaków za pomocą javascript?

Na przykład;

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

var fnc = aMethod(s);

Jeśli jest to ciąg znaków, chcę funkcji o nazwie fnc. I fnc(); wyskakuje ekran alertu.

eval("alert(1);") to nie rozwiązuje mojego problemu.

Author: cdeszaq, 2011-10-04

8 answers

Dodałem test jsperf dla 4 różnych sposobów tworzenia funkcji z łańcucha znaków:

  • Using RegExp with Function class

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

  • Użycie klasy funkcji z "return"

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

  • Użycie oficjalnego konstruktora funkcji

    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 próbki wyników: Tutaj wpisz opis obrazka Tutaj wpisz opis obrazka

 38
Author: hanhp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 01:05:34

Lepszym sposobem tworzenia funkcji z ciągu znaków jest użycie Function:

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

Zaletą / wadą jest to, że zmienne w bieżącym zakresie (jeśli nie globalnym) nie mają zastosowania do nowo skonstruowanej funkcji.

Przekazywanie argumentów jest również możliwe:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'
 159
Author: Lekensteyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-04 15:16:15

Jesteś blisko.

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

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

//Call the function
test();

Oto działające skrzypce .

 37
Author: James Hill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-04 15:13:33

Tak, użycie {[2] } jest świetnym rozwiązaniem, ale możemy pójść nieco dalej i przygotować uniwersalny parser, który parsuje łańcuch i przekonwertować go do prawdziwej funkcji JavaScript...

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;
    };
}

Przykłady użycia:

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();

Tutaj jest jsfiddle

 13
Author: Mr. Pumpkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-13 20:52:31

Dynamiczne nazwy funkcji w JavaScript

Użycie 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'

Źródło: http://marcosc.com/2012/03/dynamic-function-names-in-javascript/

Użycie eval

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

Użycie sjsClass

Https://github.com/reduardo7/sjsClass

Przykład

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

var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'
 11
Author: Eduardo Cuomo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-08 19:15:12

Ta technika może być ostatecznie równoważna metodzie eval, ale chciałem ją dodać, ponieważ może być przydatna dla niektórych.

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

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

document.body.appendChild( newCode );

Jest to funkcjonalnie jak dodanie elementu

...

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

</body>
</html>
 5
Author: David Newberry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 05:21:06

Użyj new Function() z powrotem w środku i wykonaj go natychmiast.

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

var new_fn = new Function("return " + s)()
console.log(new_fn)
new_fn()
 1
Author: Fernando Carvajal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-27 02:16:29

Przykład z dynamicznymi argumentami:

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]))
 0
Author: brunettdan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 01:16:41