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.