Frage Wie führe ich eine JavaScript-Funktion aus, wenn ich ihren Namen als String habe?


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

Abhängig von den Umständen muss ich möglicherweise auch verschiedene Argumente in die Methode eingeben.

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


848
2017-12-11 15:47


Ursprung


Antworten:


Verwenden Sie Eval nicht, außer Sie absolut, positiv habe keine andere Wahl.

Wie bereits erwähnt, wäre es am besten, so etwas zu tun:

window["functionName"](arguments);

Dies funktioniert jedoch nicht mit einer Namespace-Funktion:

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

So würdest du das machen:

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

Um das zu vereinfachen und etwas Flexibilität zu bieten, gibt es hier eine Komfortfunktion:

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

Du würdest es so nennen:

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

Beachten Sie, dass Sie in jedem beliebigen Kontext übergeben können, also würde dies dasselbe wie oben tun:

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

1224
2017-12-11 16:15



Ich dachte nur, ich würde eine etwas veränderte Version von Jason Bunting ist sehr hilfreiche Funktion.

Zuerst habe ich die erste Anweisung vereinfacht, indem ich einen zweiten Parameter anliefere Scheibe(). Die ursprüngliche Version funktionierte in allen Browsern außer IE.

Zweitens habe ich ersetzt Dies mit Kontext in der Rücksendeaussage; Andernfalls, Dies zeigte immer auf 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);
}

89
2017-12-04 02:16



Die Antwort auf diese andere Frage zeigt Ihnen, wie Sie das tun: Javascript-Äquivalent von 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);

obwohl dies extrem unsicher ist, es sei denn, Sie sind sich absolut sicher, was Sie auswerten.


51
2017-12-11 15:49



Könnten Sie das nicht einfach tun:

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

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


43
2017-08-16 20:56



Ich denke, ein eleganter Weg, dies zu tun, besteht darin, Ihre Funktionen in einem Hash-Objekt zu definieren. Dann können Sie über den String eine Referenz auf diese Funktionen aus dem Hash erhalten. 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.


29
2018-06-02 17:13



Zwei Dinge:

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

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


21
2017-12-11 16:01



Mit ES6 können Sie Klassenmethoden namentlich aufrufen:

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

die Ausgabe wäre:

1
2

18
2017-07-08 10:22



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

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

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


12
2017-11-11 18:22



Alle Antworten gehen davon aus, dass auf die Funktionen über den globalen Gültigkeitsbereich (Fenster) zugegriffen werden kann. Das OP machte diese Annahme jedoch nicht.

Wenn die Funktionen in einem lokalen Bereich (alias Closure) leben und nicht von einem anderen lokalen Objekt referenziert werden, Pech: Sie müssen verwenden eval () AFAIK, sehen Rufen Sie die lokale Funktion in JavaScript dynamisch auf


12
2018-02-04 18:03



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

8
2018-01-25 13:38



Hier ist mein Beitrag zu den exzellenten Antworten von Jason Bunting / Alex Nazarov, wo ich die von Crashalot geforderte Fehlerprüfung einschließe.

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

ermöglicht es Ihnen, eine JavaScript-Funktion durch den Namen in einer Zeichenfolge namens Namespace oder global, mit oder ohne Argumente (einschließlich Array-Objekte) zu nennen, geben Feedback zu allen aufgetretenen Fehlern (hoffentlich fangen sie).

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
  */

8
2018-02-11 01:08