So führen Sie eine JavaScript-Funktion aus, wenn ich ihren Namen als Zeichenfolge habe

1050

Ich habe den Namen einer Funktion in JavaScript als Zeichenfolge. Wie konvertiere ich das in einen Funktionszeiger, damit ich ihn später aufrufen kann?

Abhängig von den Umständen muss ich möglicherweise auch verschiedene Argumente an die Methode übergeben.

Einige der Funktionen können die Form von haben namespace.namespace.function(args[...]).

Kieron
quelle

Antworten:

1438

Verwenden evalSie es nur , wenn Sie absolut keine andere Wahl haben.

Wie bereits erwähnt, wäre die Verwendung von so etwas der beste Weg, dies zu tun:

window["functionName"](arguments);

Dies funktioniert jedoch nicht mit einer Namespace-Funktion:

window["My.Namespace.functionName"](arguments); // fail

So würden Sie das machen:

window["My"]["Namespace"]["functionName"](arguments); // succeeds

Um dies zu vereinfachen und Flexibilität zu bieten, gibt es hier eine praktische Funktion:

function executeFunctionByName(functionName, context /*, args */) {
  var args = Array.prototype.slice.call(arguments, 2);
  var namespaces = functionName.split(".");
  var func = namespaces.pop();
  for(var i = 0; i < namespaces.length; i++) {
    context = context[namespaces[i]];
  }
  return context[func].apply(context, args);
}

Sie würden es so nennen:

executeFunctionByName("My.Namespace.functionName", window, arguments);

Beachten Sie, dass Sie in einem beliebigen Kontext übergeben können. Dies würde also wie oben beschrieben erfolgen:

executeFunctionByName("Namespace.functionName", My, arguments);
Jason Bunting
quelle
4
Sie wissen, dass Sie nicht das gesamte "func" -Konstrukt benötigen? "context.apply" allein ist in Ordnung
annakata
16
Klar, das weiß ich - aber die Art und Weise, wie ich die Funktion geschrieben habe, bietet denjenigen, die sie lesen, Klarheit, die möglicherweise nicht vollständig verstehen, was gerade passiert. Ich habe diese Funktion geschrieben und festgestellt, dass Leute, die sie lesen, möglicherweise Hilfe benötigen. Ich werde jedoch eine Alternative anbieten, da Sie gefragt haben ...
Jason Bunting
108
Scratch that - der Code ist klar genug und diejenigen, die es wissen, wissen es. Wenn Sie wie ich sind und wissen, was Sie tun, können Sie solche Änderungen einfach selbst vornehmen, wenn Sie diesen Code verwendet haben. Der Stapelüberlauf dient dazu, andere zu unterrichten, und ich denke, mein Code ist für Anfänger leichter zu verstehen. Trotzdem danke!
Jason Bunting
4
Gibt es eine Situation, in der window ["funcName"] undefiniert zurückgibt? Das ist das Problem, das ich gerade habe. Der aufrufende Code und die Funktion werden in zwei separaten js-Dateien definiert. Ich habe versucht, sie derselben Datei hinzuzufügen, aber das machte keinen Unterschied.
Codemonkey
5
Ich denke, hier gibt es ein Problem. Wenn Sie anrufen My.Namespace.functionName(), thiswird auf das My.NamespaceObjekt verwiesen. Aber wenn Sie anrufen executeFunctionByName("My.Namespace.functionName", window), gibt es keine Möglichkeit, sich thisauf dasselbe zu beziehen. Möglicherweise sollte der letzte Namespace als Bereich verwendet werden, oder windowwenn keine Namespaces vorhanden sind. Oder Sie können dem Benutzer erlauben, den Bereich als Argument anzugeben.
JW.
100

Ich dachte nur, ich würde eine leicht veränderte Version von Jason Bunting 'sehr hilfreicher Funktion veröffentlichen .

Erstens habe ich die erste Anweisung vereinfacht, indem ich Slice () einen zweiten Parameter gegeben habe . Die Originalversion funktionierte in allen Browsern außer IE einwandfrei.

Zweitens habe ich ersetzt dies mit Kontext in der return - Anweisung; Andernfalls zeigte dies immer auf das Fenster, wenn die Zielfunktion ausgeführt wurde.

function executeFunctionByName(functionName, context /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for (var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    return context[func].apply(context, args);
}
Alex Nazarov
quelle
Es wird nicht überprüft, ob "Funktionsname" tatsächlich vorhanden ist.
Crashalot
Ich denke, Macs Antwort wird unterschätzt. Ich bin kein Experte, aber es scheint gut durchdacht und robust.
Martin Hansen Lennox
65

Die Antwort auf diese andere Frage zeigt Ihnen, wie das geht: Javascript-Äquivalent zu Pythons Einheimischen ()?

Grundsätzlich kann man sagen

window["foo"](arg1, arg2);

oder wie viele andere vorgeschlagen haben, können Sie einfach eval verwenden:

eval(fname)(arg1, arg2);

Dies ist jedoch äußerst unsicher, es sei denn, Sie sind sich absolut sicher, was Sie bewerten.

Eli Courtwright
quelle
6
Die erste Form ist weitaus vorzuziehen
Annakata
19
Verwenden Sie eval nur als letzten Ausweg, wenn alles andere fehlschlägt.
Jason Bunting
1
Es ist ... aber wird es mit Funktionen wie diesen funktionieren: xyz (args)?
Kieron
@ Keiron: Ja. siehe meine Antwort unten
annakata
55

Könnten Sie das nicht einfach so machen:

var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();

Mit dieser Methode können Sie auch jedes andere JavaScript ausführen.

Coley
quelle
3
funktioniert, wenn gerade Argumente mit der Funktion übergeben werden
adeel41
Was ist mit Funktionsrückgabe?
Peter Denev
12
Wie unterscheidet sich das von eval("My.Namespace.functionName()");?
Developerbmw
@ PeterDenev ändern Sie einfach die erste Zeile zuvar codeToExecute = "return My.Namespace.functionName()";
Developerbmw
2
@developerbmw, hier ist Antwort stackoverflow.com/questions/4599857/…
Tejasvi Hegde
48

Ich denke, eine elegante Möglichkeit, dies zu tun, besteht darin, Ihre Funktionen in einem Hash-Objekt zu definieren. Dann können Sie mithilfe der Zeichenfolge einen Verweis auf diese Funktionen aus dem Hash haben. z.B

var customObject = {
  customFunction: function(param){...}
};

Dann können Sie anrufen:

customObject['customFunction'](param);

Wobei customFunction eine Zeichenfolge ist, die einer in Ihrem Objekt definierten Funktion entspricht.

Ruben Daddario
quelle
@ibsenv, vielen Dank für Ihren Kommentar, der mir hilft, diese Antwort als die beste zu identifizieren. Ich habe ein Array von Funktionsobjekten erstellt und dieses wiederum verwendet, um ein Array von verzögerten Versprechungen zu erstellen. Ich habe unten einen Beispielcode eingefügt. (Ich wollte keine neue Antwort erstellen und Rubens Antwort ausleihen .)
user216661
Funktion getMyData (arrayOfObjectsWithIds) {var functionArray = arrayOfObjectsWithIds.map (Funktion (Wert) {return {myGetDataFunction: MyService.getMyData (value.id)};}) var versprechen = functionArray.map (Funktion (getDataFunction) {var deferred = q.defer (); getDataFunction.myGetDataFunction.success (Funktion (Daten) {deferred.resolve (Daten)}). error (Funktion (Fehler) {deferred.reject ();}); return deferred.promise;}); $ q.all (verspricht) .then (function (dataArray) {// mache Sachen})};
user216661
Dies funktioniert hervorragend. Ich füge nur Unterstrich / lodash hinzu, um zu überprüfen, ob es eine Funktion ist. Und dann laufen
elporfirio
35

Mit ES6 können Sie nach Namen auf Klassenmethoden zugreifen:

class X {
  method1(){
    console.log("1");
  }
  method2(){
    this['method1']();
    console.log("2");
  }
}
let x  = new X();
x['method2']();

die Ausgabe wäre:

1
2
nils petersohn
quelle
1
Bestes Javascript PURE ... Gott .. Klasse löschen funktioniert nicht und aber es ist ok. Vielen Dank!
KingRider
1
Das ist das, wonach ich schon lange gesucht habe. Vielen Dank!
PaladiN
ES2015 hat hier nichts zu tun. Sie können dasselbe Ziel mit reinen Objekten oder Prototypdelegierung über erreichen Object.create(). const myObj = {method1 () {console.log ('1')}, method2 () {console.log ('2')}} myObj ['method1'] (); // 1 myObj ['method2'] (); // 2
Sminutoli
1
Das ist Gold !!! Ich bin überrascht, dass ich noch nie daran gedacht habe. Nett!!!
thxmike
Ich denke auch, dass dies der beste Weg ist, um unser Ziel zu erreichen.
Chris Jung
24

Zwei Dinge:

  • Vermeiden Sie Eval, es ist schrecklich gefährlich und langsam

  • zweitens spielt es keine Rolle, wo Ihre Funktion existiert, "globale" -ness ist irrelevant. x.y.foo()kann durch x.y['foo']()oder x['y']['foo']()oder sogar aktiviert werden window['x']['y']['foo'](). Sie können so unbegrenzt verketten.

Annakata
quelle
1
Sie können jedoch nicht window ['xyz'] ()
ausführen
17

Bei allen Antworten wird davon ausgegangen, dass auf die Funktionen über den globalen Bereich (Fenster) zugegriffen werden kann. Das OP hat diese Annahme jedoch nicht getroffen.

Wenn die Funktionen in einem lokalen Bereich (auch als Closure bezeichnet) ausgeführt werden und nicht von einem anderen lokalen Objekt referenziert werden, Pech: Sie müssen eval()AFAIK verwenden, siehe Dynamisches Aufrufen der lokalen Funktion in Javascript

Wolfgang Kühn
quelle
2
Alter (oder Typ), vielen Dank, dass Sie darauf hingewiesen haben! Ich dachte, ich würde für eine Sekunde verrückt.
Funktr0n
13

Sie müssen nur Ihre Zeichenfolge in einen Zeiger von konvertieren window[<method name>]. Beispiel:

var function_name = "string";
function_name = window[function_name];

und jetzt können Sie es wie einen Zeiger verwenden.

Amirali
quelle
Dies scheint ein viel sichererer Weg zu sein.
James Poulose
12

Hier ist mein Beitrag zu den hervorragenden Antworten von Jason Bunting / Alex Nazarov, in denen ich die von Crashalot angeforderte Fehlerprüfung einbeziehe.

Angesichts dieser (erfundenen) Präambel:

a = function( args ) {
    console.log( 'global func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] );
    }
};
ns = {};
ns.a = function( args ) {
    console.log( 'namespace func passed:' );
    for( var i = 0; i < arguments.length; i++ ) {
        console.log( '-> ' + arguments[ i ] ); 
    }
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};

dann die folgende Funktion:

function executeFunctionByName( functionName, context /*, args */ ) {
    var args, namespaces, func;

    if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }

    if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }

    if( typeof context !== 'undefined' ) { 
        if( typeof context === 'object' && context instanceof Array === false ) { 
            if( typeof context[ functionName ] !== 'function' ) {
                throw context + '.' + functionName + ' is not a function';
            }
            args = Array.prototype.slice.call( arguments, 2 );

        } else {
            args = Array.prototype.slice.call( arguments, 1 );
            context = window;
        }

    } else {
        context = window;
    }

    namespaces = functionName.split( "." );
    func = namespaces.pop();

    for( var i = 0; i < namespaces.length; i++ ) {
        context = context[ namespaces[ i ] ];
    }

    return context[ func ].apply( context, args );
}

Mit dieser Funktion können Sie eine Javascript-Funktion anhand eines Namens aufrufen, der in einer Zeichenfolge mit oder ohne Argument (einschließlich Array-Objekten) gespeichert ist, und Feedback zu aufgetretenen Fehlern geben (hoffentlich abfangen).

Die Beispielausgabe zeigt, wie es funktioniert:

// calling a global function without parms
executeFunctionByName( 'a' );
  /* OUTPUT:
  global func passed:
  */

// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
  /* OUTPUT:
  global func passed:
  -> 123
  */

// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
  /* OUTPUT:
  namespace func passed:
  */

// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  */

// calling a namespaced function, with explicit context as separate arg, passing a string literal and array 
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
  /* OUTPUT:
  namespace func passed:
  -> No Such Agency!
  -> 7,is the man
  */

// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
  /* OUTPUT:
  global func passed:
  -> nsa
  */

// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
  /* OUTPUT:
  Uncaught n_s_a is not a function
  */

// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
  /* OUTPUT:
  Uncaught Snowden is not a function
  */

// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
  /* OUTPUT:
  Uncaught [object Object].a is not a function
  */

// calling no function
executeFunctionByName();
  /* OUTPUT:
  Uncaught function name not specified
  */

// calling by empty string
executeFunctionByName( '' );
  /* OUTPUT:
  Uncaught  is not a function
  */

// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
  /* OUTPUT:
  Uncaught [object Object].noSuchAgency is not a function
  */
Mac
quelle
Keine Ahnung ... es ist eine sehr gute Anstrengung, so klar. Aber klingt für mich "zu breit" ...
TechNyquist
2
Huh? SO ist eine Frage / Antwort / Lehrplattform. Ich werde gerne alle Beispiele zur Verfügung stellen, die mir einfallen, um hoffentlich die Beleuchtung zu vermitteln. Für mich ist das der Punkt .
Mac
Wenn Sie den Funktionsnamen trotzdem bewerten, warum nicht einfach diesen verwenden?
Daten
Das funktioniert bei mir nicht. Ich habe eine Namespace-Funktion abcd, wobei d der Funktionsname ist. Der Aufruf executeFunctionByName ("abcd", window) schlägt online fehl und prüft, ob der if( typeof context[ functionName ] !== 'function' )Kontext - window - definiert ist, ein Objekt und ein Array ist, aber das Fenster ['abcd'] existiert nicht, da es im akzeptierten als Problem identifiziert wurde Antwort: window["My.Namespace.functionName"](arguments); // fail
Akousmata
12

Je nachdem, wo Sie sich befinden, können Sie auch Folgendes verwenden:

this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();

oder in nodejs

global["funcname"]()
Zibri
quelle
9

Wenn Sie eine Funktion eines Objekts anstelle einer globalen Funktion mit aufrufen möchten window["functionName"]. Du kannst es so machen;

var myObject=new Object();
myObject["functionName"](arguments);

Beispiel:

var now=new Date();
now["getFullYear"]()
Ahmet DAL
quelle
8

ACHTUNG!!!

Man sollte aus zwei Gründen versuchen, das Aufrufen einer Funktion per String in JavaScript zu vermeiden:

Grund 1: Einige Code-Verschleierer zerstören Ihren Code, da sie die Funktionsnamen ändern und die Zeichenfolge ungültig machen.

Grund 2: Es ist viel schwieriger, Code zu verwalten, der diese Methode verwendet, da es viel schwieriger ist, die Verwendung der von einer Zeichenfolge aufgerufenen Methoden zu finden.

dykstrad
quelle
7

Hier ist mein Es6-Ansatz, mit dem Sie Ihre Funktion anhand ihres Namens als Zeichenfolge oder ihres Funktionsnamens aufrufen und verschiedene Arten von Argumenten an verschiedene Arten von Funktionen übergeben können:

function fnCall(fn, ...args)
{
  let func = (typeof fn =="string")?window[fn]:fn;
  if (typeof func == "function") func(...args);
  else throw new Error(`${fn} is Not a function!`);
}


function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 + "  and   " + arg2)}
function example3(){console.log("No arguments!")}

fnCall("example1", "test_1");
fnCall("example2", "test_2", "test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console

Pouyan
quelle
6

Überrascht, dass setTimeout nicht erwähnt wurde.

So führen Sie eine Funktion ohne Argumente aus:

var functionWithoutArguments = function(){
    console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);

So führen Sie eine Funktion mit Argumenten aus:

var functionWithArguments = function(arg1, arg2) {
    console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");

So führen Sie eine Funktion mit tiefem Namespace aus:

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}
setTimeout("_very._deeply._defined._function(40,50)", 0);
abhishekisnot
quelle
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag - Sie können jederzeit Ihre eigenen Beiträge kommentieren, und sobald Sie einen ausreichenden Ruf haben, können Sie dies tun jeden Beitrag kommentieren .
AstroCB
Bitte fügen Sie ein Beispiel hinzu, wie Sie runMemit ein paar Argumenten aufrufen würden .
Lexicore
1
@lexicore Ich habe für das Löschen in einer Überprüfungswarteschlange gestimmt , da es keine eindeutige Antwort auf die Frage liefert und für sich genommen von geringem Wert ist.
AstroCB
1
Diese Methode weist möglicherweise einen großen Fehler auf, da die Ausführung der Rendering- Warteschlange beendet wird und dieser Aufruf ausgeführt wird asynchron wird
PeterM
1
Ich mag diese Antwort, sie scheint für meine Anforderungen zu funktionieren.
Quintonn
3

Also, wie andere sagten, ist definitiv die beste Option:

window['myfunction'](arguments)

Und wie Jason Bunting sagte , funktioniert es nicht, wenn der Name Ihrer Funktion ein Objekt enthält:

window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work

Hier ist meine Version einer Funktion, die alle Funktionen nach Namen ausführt (einschließlich eines Objekts oder nicht):

my = {
    code : {
        is : {
            nice : function(a, b){ alert(a + "," + b); }
        }
    }
};

guy = function(){ alert('awesome'); }

function executeFunctionByName(str, args)
{
    var arr = str.split('.');
    var fn = window[ arr[0] ];
    
    for (var i = 1; i < arr.length; i++)
    { fn = fn[ arr[i] ]; }
    fn.apply(window, args);
}

executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');

pmrotule
quelle
3
  let t0 = () => { alert('red0') }
  var t1 = () =>{ alert('red1') }
  var t2 = () =>{ alert('red2') }
  var t3 = () =>{ alert('red3') }
  var t4 = () =>{ alert('red4') }
  var t5 = () =>{ alert('red5') }
  var t6 = () =>{ alert('red6') }

  function getSelection(type) {
    var evalSelection = {
      'title0': t0,
      'title1': t1,
      'title2': t2,
      'title3': t3,
      'title4': t4,
      'title5': t5,
      'title6': t6,
      'default': function() {
        return 'Default';
      }
    };
    return (evalSelection[type] || evalSelection['default'])();
  }
  getSelection('title1');

Eine OOP-Lösung ...

Leo Lanese
quelle
2

Noch ein Detail zu den Posts von Jason und Alex. Ich fand es hilfreich, dem Kontext einen Standardwert hinzuzufügen. Einfach context = context == undefined? window:context;am Anfang der Funktion setzen. Sie können windowzu einem beliebigen bevorzugten Kontext wechseln und müssen dann nicht jedes Mal dieselbe Variable übergeben, wenn Sie dies in Ihrem Standardkontext aufrufen.

Bradley Shrader
quelle
2

Um die Antwort von Jason Bunting zu ergänzen: Wenn Sie Nodejs oder ähnliches verwenden (und dies funktioniert auch in Dom Js), können Sie thisstattdessen window(und denken Sie daran: eval is evil :

this['fun'+'ctionName']();
Cilan
quelle
2

In meinem Code ist etwas sehr Ähnliches. Ich habe eine vom Server generierte Zeichenfolge, die einen Funktionsnamen enthält, den ich als Rückruf für eine Bibliothek eines Drittanbieters übergeben muss. Ich habe also einen Code, der den String nimmt und einen "Zeiger" auf die Funktion zurückgibt, oder null, wenn er nicht gefunden wird.

Meine Lösung war der " sehr hilfreichen Funktion von Jason Bunting " * sehr ähnlich , obwohl sie nicht automatisch ausgeführt wird und der Kontext immer im Fenster angezeigt wird. Dies kann jedoch leicht geändert werden.

Hoffentlich ist dies für jemanden hilfreich.

/**
 * Converts a string containing a function or object method name to a function pointer.
 * @param  string   func
 * @return function
 */
function getFuncFromString(func) {
    // if already a function, return
    if (typeof func === 'function') return func;

    // if string, try to find function or method of object (of "obj.func" format)
    if (typeof func === 'string') {
        if (!func.length) return null;
        var target = window;
        var func = func.split('.');
        while (func.length) {
            var ns = func.shift();
            if (typeof target[ns] === 'undefined') return null;
            target = target[ns];
        }
        if (typeof target === 'function') return target;
    }

    // return null if could not parse
    return null;
}
Nomaed
quelle
1

Ich kann nicht widerstehen, einen anderen Trick zu erwähnen, der hilft, wenn Sie eine unbekannte Anzahl von Argumenten haben, die auch als Teil der Zeichenfolge übergeben werden, die den Funktionsnamen enthält. Zum Beispiel:

var annoyingstring = 'call_my_func(123, true, "blah")';

Wenn Ihr Javascript auf einer HTML-Seite ausgeführt wird, benötigen Sie lediglich einen unsichtbaren Link. Sie können eine Zeichenfolge an das onclickAttribut übergeben und die clickMethode aufrufen .

<a href="#" id="link_secret"><!-- invisible --></a>

$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();

Oder erstellen Sie das <a>Element zur Laufzeit.

Magnus Smith
quelle
Kreative Lösung, dies funktioniert jedoch nicht für Argumente vom Typ Objekt oder Array.
Dennis Heiden
1
Dies verwendet eval unter der Haube ... Und wirklich um den heißen
Juan Mendes
1

Am einfachsten ist es, darauf zuzugreifen, als hätte es ein Element

window.ClientSideValidations.forms.location_form

ist das gleiche wie

window.ClientSideValidations.forms['location_form']
verrückt
quelle
1

Sie können die Javascript-Funktion in eval("functionname as string")beiden aufrufen . Wie unten: (eval ist reine Javascript-Funktion)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

Arbeitsbeispiel: https://jsfiddle.net/suatatan/24ms0fna/4/

Suat Atan PhD
quelle
Dies funktioniert gut und es ist so einfach
Carlos E
1
Und auch sehr langsam.
Marco
1

Das funktioniert bei mir:

var command = "Add";
var tempFunction = new Function("Arg1","Arg2", "window." + command + "(Arg1,Arg2)");
tempFunction(x,y);

Ich hoffe das funktioniert.

DevAshish
quelle
1

Ich glaube nicht, dass Sie komplizierte Zwischenfunktionen oder Auswertungen benötigen oder von globalen Variablen wie window abhängig sind:

function fun1(arg) {
  console.log(arg);
}

function fun2(arg) {
  console.log(arg);
}

const operations = {
  fun1,
  fun2
};

let temp = "fun1";

try {
  // You have to use square brackets property access
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
  // You can use variables
  operations[temp]("Hello World");
} catch (error) {
  console.error(error);
}

Es funktioniert auch mit importierten Funktionen:

// mode.js
export function fun1(arg) {
  console.log(arg);
}

export function fun2(arg) {
  console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";

const operations = {
  fun1,
  fun2
};

try {
  operations["fun1"]("Hello World");
  operations["fun2"]("Hello World");
} catch (error) {
  console.error(error);
}
SnnSnn
quelle
0

Ohne Verwendung können eval('function()')Sie mit eine neue Funktion erstellen new Function(strName). Der folgende Code wurde mit FF, Chrome, IE getestet.

<html>
<body>
<button onclick="test()">Try it</button>
</body>
</html>
<script type="text/javascript">

  function test() {
    try {    
        var fnName = "myFunction()";
        var fn = new Function(fnName);
        fn();
      } catch (err) {
        console.log("error:"+err.message);
      }
  }

  function myFunction() {
    console.log('Executing myFunction()');
  }

</script>
Ithar
quelle
0
use this

function executeFunctionByName(functionName, context /*, args */) {
      var args = [].slice.call(arguments).splice(2);
      var namespaces = functionName.split(".");
      var func = namespaces.pop();
      for(var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
      }
      return context[func].apply(context, args);
    }
Pratik
quelle
1
Warum? Antworten ohne Erklärung sind höchstwahrscheinlich nutzlos.
Daniel W.
0

Einfach aussehen:

var namefunction = 'jspure'; // String

function jspure(msg1 = '', msg2 = '') { 
  console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument

// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple

Bestehende andere Typfunktion ist Klasse und Aussehen Beispiel nils petersohn

KingRider
quelle
0

Danke für die sehr hilfreiche Antwort. Ich benutze die Funktion von Jason Bunting in meinen Projekten.

Ich habe es erweitert, um es mit einem optionalen Zeitlimit zu verwenden, da die normale Methode zum Festlegen eines Zeitlimits nicht funktioniert. Siehe abhishekisnots Frage

function executeFunctionByName(functionName, context, timeout /*, args */ ) {
	var args = Array.prototype.slice.call(arguments, 3);
	var namespaces = functionName.split(".");
	var func = namespaces.pop();
	for (var i = 0; i < namespaces.length; i++) {
		context = context[namespaces[i]];
	}
	var timeoutID = setTimeout(
		function(){ context[func].apply(context, args)},
		timeout
	);
    return timeoutID;
}

var _very = {
    _deeply: {
        _defined: {
            _function: function(num1, num2) {
                console.log("Execution _very _deeply _defined _function : ", num1, num2);
            }
        }
    }
}

console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );

Neo
quelle