Ottieni object funzione JavaScript dal suo nome come stringa?

In JavaScript, se ho una stringa in una variabile, c’è un modo per ottenere un riferimento all’object funzione che ha quel nome corrispondente? Nota che jQuery è disponibile per me, così posso usare anche i suoi metodi di supporto.

Per esempio:

myFunction = function(){}; var func_name = "myFunction"; var myFunctionPtr = ??? //how to get the function from the name 

Grazie

se sai che è una funzione globale puoi usare:

 var functPtr = window[func_name]; //functPtr() 

Altrimenti sostituire la finestra con l’object genitore contenente la funzione.

Ho appena fatto un rapido test in Firebug e sono stato in grado di ottenere la funzione dal nome semplicemente eval() il nome … Mi sento sporco usando eval() , ma sembra che il lavoro sia svolto abbastanza bene.

 var myFunctionPtr = eval(func_name); 

Questo non è mai un approccio preferito. Invece di mantenere il nome della funzione in func_name , avresti potuto mantenere il riferimento a una funzione altrettanto correttamente in qualcosa come func_to_call .

Se si richiede assolutamente di mantenere la funzione di riferimento come stringa, in genere si utilizza una tabella hash per mappare un nome arbitrario su una variabile (JS ha funzioni di prima class che lo rendono ansible)

 myFunction = function(){}; var obj = {func_name: myFunction}; obj['func_name']();//executes the function 

Fiddled (non so perché, è una sceneggiatura così piccola 🙂

È stato suggerito di utilizzare eval(func_name) , tuttavia questo potrebbe rapidamente perdere il controllo a causa dell’oscillazione JS.

Hai anche dichiarato il tuo myFunction = function(){}; come variabile globale. Da una parte, ti permette di fare riferimento come window[func_name] ma d’altra parte inquina l’ambito globale.

questo [nome_funzione] dovrebbe darti la funzione.

 var myfunc = this[func_name]; myfunc(); 

Dipende da dove e come la funzione è (o non è) dichiarata.

Se si tratta di una syntax globale e non dichiarata tramite let name = ... o const name = ... (e non è un costruttore di classi dichiarato con la class ), è ansible verificarlo cercando come proprietà sull’object globale. (Queste avvertenze sono tutte cose ES2015, più sotto.) È ansible ottenere un riferimento all’object globale tramite this in modalità libera nell’ambito globale; i browser ti danno anche una window chiamata globale. Quindi assumendo un browser:

 if (typeof window[func_name] === "function") { // .... } 

Se potrebbe non essere globale, ma è solo di portata perché il tuo codice si chiude su di esso, o se è stato creato utilizzando uno di quei meccanismi ES2015 che ho menzionato, non c’è davvero un buon modo per controllare altro che eval :

 if (eval("typeof " + func_name) === "function") { // .... } 

L’utilizzo di eval è l’ultima risorsa e devi solo usarlo con un input rigorosamente controllato. Ma quando è necessario e hai un input rigorosamente controllato, va bene.


Informazioni sui caveat ES2015:

Le nuove let , const e class sono bestie molto interessanti: se utilizzate nell’ambito globale, creano globals, ma non creano proprietà sull’object globale. A partire da ES2015, sebbene tutte le proprietà dell’object globale siano globali, non tutti i globali sono proprietà dell’object globale. Fa tutto parte del tentativo di contenere lo spazio dei nomi globale altamente inquinato e offre anche una maggiore sicurezza al modello di bind JavaScript. (Ora che abbiamo veri moduli.)

Quindi (nota che questo funzionerà solo con browser all’avanguardia):

 // Global scope, in a browser (because I used `window` and `document.body`) that // implements this aspect of ES2015 (as I write this, Firefox's SpiderMonkey // doesn't, Chrome's V8 does on the latest Chrome; expect SpiderMonkey and IE // to catch up pretty quick (didn't test IE Edge, maybe it's already there) // Strict mode isn't required for this behavior, but for the moment V8 only // supports the block-scoped constructs in strict mode. "use strict"; let tbody = setup(); // Old-fashioned var: Creates a property on the global object, so // we get "function, function" var f1 = function() { /*...*/ }; result("var declaration", typeof f1, typeof window["f1"]); // Function declaration: Creates a property on the global object, so // "function, function" function f2() {} result("function declaration", typeof f2, typeof window["f2"]); // `let` declaration: Doesn't create property on global object, so // "function, undefined" let f3 = function() { /*...*/ }; result("let declaration", typeof f3, typeof window["f3"]); // `const` declaration: Doesn't create property on global object, so // "function, undefined" const f4 = function() { /*...*/ }; result("const declaration", typeof f4, typeof window["f4"]); // `class` declaration: Doesn't create property on global object, so // "function, undefined" class C1 {} result("class declaration", typeof C1, typeof window["C1"]); function setup() { document.body.insertAdjacentHTML( "beforeend", "" + "" + "" + "" + "" + "
testglobalprop
" ); return document.body.querySelector("tbody"); } function result(label, direct, win) { tbody.insertAdjacentHTML( "beforeend", "" + [label, direct, win].join("") + "" ); }
 body { font-family: sans-serif; } table { border-collapse: collapse; } th, td { border: 1px solid #ddd; padding: 4px 8px; } 

Usa eval:

 myFunction = function(){}; var func_name = "myFunction"; var myFunctionPtr = eval(func_name); 

Un modo sicuro per fare è sandboxare la presunta funzione durante il test del suo tipo:

 function isFunction(expr) { function sandboxTemplate() { var window, document, alert; // etc. try { return typeof $expr$ == "function"; } catch (e) { return false; } } try { var sandbox = new Function( sandboxTemplate.toString().replace("$expr$", expr) + "return sandboxTemplate()"); return sandbox(); } catch (e) { return false; } } function test(expr) { document.write("
\"" + expr + "\" is " + (isFunction(expr) ? "" : "not ") + "a function
"); } /* Let's do some testing */ function realFunction() { } test("realFunction"); // exists! test("notHere"); // non-existent test("alert('Malicious')"); // attempt to execute malicious code! test("syntax error {"); // attempt to blow us up!

Il risultato:

  • “realFunction” è una funzione
  • “notHere” non è una funzione
  • “alert (‘Malicious’)” non è una funzione
  • “syntax error {” non è una funzione

Il codice sandboxing potrebbe essere scritto in modo più conciso, ma mi piace usare le funzioni “template” invece di incorporare il codice JS come stringhe letterali.

E, oh, lo fa bene senza usare eval – anche se si può sostenere che l’uso di un costruttore di Function non è diverso da una eval .

trovato la funzione e poi chiamarli

 autoCallBack : function(_action){ $(".module").each(function(){ var modulName = $(this).attr("id"); if( isFunction(modulName) ){ eval(modulName)(); } }); } isFunction : function(_functionName){ try { eval(_functionName); } catch (error) { return false; } return true; } 

Per NodeJs

Scrivi le tue funzioni in un file separato ed esportale e usale con il nome di riferimento per chiamarle, Mi piace

 // functions.js var funcOne = function(){ console.log('function ONE called') } module.exports={ // name_exported : internal_name funcOne : funcOne } 

Usa la funzione definita in functions.js in index.js :

 // index.js var methods = require('./functions.js') // path to functions.js methods['funcOne']() 

PRODUZIONE :

 > node index.js > function ONE called