C'è un modo per creare una funzione da una stringa con javascript?


107

Per esempio;

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

var fnc = aMethod(s);

Se questa è la stringa, voglio una funzione chiamata fnc. E viene fnc();visualizzata la schermata di avviso.

eval("alert(1);") non risolve il mio problema.

Risposte:


73

Ho aggiunto un test jsperf per 4 diversi modi per creare una funzione dalla stringa:

  • Utilizzo di RegExp con la classe Function

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

  • Utilizzo della classe Function con "return"

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

  • Utilizzo del costruttore di funzioni ufficiale

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

  • Utilizzando Eval

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

http://jsben.ch/D2xTG

2 campioni di risultati: inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


@KthProg Rilassati;). Non è sempre male, come questa situazione, il jsperf al momento è inattivo, fortunatamente ho aggiunto gli screenshot dei risultati prima che fosse disattivato, quando ho ricevuto il commento da Bulk.
phnah

@KthProg FYI questa era una risposta predefinita generata dal sistema di moderazione :) si apre in una coda e controlliamo i problemi predeterminati, uno dei quali questo commento è progettato per risolvere. Non è una regola rigida e veloce e noterai che il commento è sotto forma di un suggerimento e non di un comando.
Dan Smith

174

Un modo migliore per creare una funzione da una stringa è usare Function:

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

Ciò ha come vantaggio / svantaggio che le variabili nell'ambito corrente (se non globali) non si applicano alla funzione appena costruita.

È anche possibile passare argomenti:

var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'

5
D'accordo, con Functionte non inquini l'ambito locale ed è per questo che evalrende l'ottimizzazione così difficile per i motori ... Con l'esempio OP, vorrei:var fnc = Function('return '+s)();
CMS

Penso che questa probabilmente dovrebbe essere la risposta accettata. È molto più sicuro di eval ().
Bryan Rayner

Tu, amico mio, meriti molti voti positivi. Questo ha il vantaggio di creare un oggetto funzione che può essere assegnato a eventi, ecc. Ad esempio: element.onclick = Function ("alert ('test');");
Ryan Griggs

1
@ RyanGriggs Nel tuo caso non hai bisogno della funzionalità "eval" quindi è meglio scrivere come element.onclick = function() { alert("test"); }.
Lekensteyn,

1
Hai ragione dal mio esempio. Tuttavia, se si desidera assegnare funzioni arbitrarie memorizzate in stringhe, il metodo è perfetto. Questo è quello che sto effettivamente cercando di fare. Ho più funzioni memorizzate in variabili stringa e desidero assegnarne una a un'azione onclick.
Ryan Griggs

38

Sei abbastanza vicino.

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

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

//Call the function
test();

Ecco un violino funzionante .


sapevo che la funzione era stata dichiarata, ma non potevo indovinare per chiamare il nome della funzione. Molte grazie.
ymutlu

4
evalAvviso obbligatorio per i futuri ricercatori: evalpuò aprire scappatoie per gli hacker: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ma se conosci i suoi pericoli e puoi evitarli, allora questo è un bel modo semplice per creare una funzione da una stringa

cosa succede se non si dispone del nome della funzione poiché proviene da un record di database?
Marcel Djaman

13

Sì, l'utilizzo Functionè un'ottima soluzione, ma possiamo andare un po 'oltre e preparare un parser universale che analizza la stringa e convertirla in una vera funzione 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;
    };
}

esempi di utilizzo:

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

ecco jsfiddle


ciao, per favore, supporta il supporto della funzione freccia a questo metodo?
sathish kumar

1
Ricevo questo errore nel typescirpt "La proprietà 'parseFunction' non esiste nel tipo 'String'."
Cegone

11

Nomi di funzioni dinamiche in JavaScript

utilizzando 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'

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

utilizzando eval

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

utilizzando sjsClass

https://github.com/reduardo7/sjsClass

Esempio

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

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

6

Questa tecnica potrebbe essere in definitiva equivalente al metodo eval, ma volevo aggiungerla, poiché potrebbe essere utile per alcuni.

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

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

document.body.appendChild( newCode );

Funzionalmente è come aggiungere questo elemento <script> alla fine del documento, ad esempio:

...

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

</body>
</html>

3

Usa il new Function()con un ritorno all'interno ed eseguilo immediatamente.

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

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


1

Un esempio con argomenti dinamici:

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]))

Grazie. Molto interessante
Дмитрий Васильев
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.