webentwicklung-frage-antwort-db.com.de

Wie verwandle ich einen String in einen JavaScript-Funktionsaufruf?

Ich habe eine Zeichenfolge wie:

settings.functionName + '(' + t.parentNode.id + ')';

dass ich in einen Funktionsaufruf wie folgt übersetzen möchte:

clickedOnItem(IdofParent);

Dies muss natürlich in JavaScript erfolgen. Wenn ich settings.functionName + '(' + t.parentNode.id + ')'; alarmiere, scheint alles korrekt zu sein. Ich muss nur die Funktion aufrufen, in die sie übersetzt werden soll.

Legende:

settings.functionName = clickedOnItem

t.parentNode.id = IdofParent
254

Zu sehen, wie ich es hasse, und ich bin nicht allein :

var fn = window[settings.functionName];
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}

Edit: Als Antwort auf @ Mahans Kommentar: In diesem speziellen Fall wäre settings.functionName"clickedOnItem". Dies würde zur Laufzeit var fn = window[settings.functionName]; In var fn = window["clickedOnItem"] Übersetzen, wodurch ein Verweis auf function clickedOnItem (nodeId) {} erhalten würde. Sobald wir einen Verweis auf eine Funktion in einer Variablen haben, können wir diese Funktion durch "Aufrufen der Variablen" aufrufen, d. H. fn(t.parentNode.id), was clickedOnItem(t.parentNode.id) entspricht, was das OP wollte.

Vollständigeres Beispiel:

/* Somewhere: */
window.settings = {
  /* [..] Other settings */
  functionName: 'clickedOnItem'
  /* , [..] More settings */
};

/* Later */
function clickedOnItem (nodeId) {
  /* Some cool event handling code here */
}

/* Even later */
var fn = window[settings.functionName]; 
/* note that settings.functionName could also be written
   as window.settings.functionName. In this case, we use the fact that window
   is the implied scope of global variables. */
if(typeof fn === 'function') {
    fn(t.parentNode.id);
}
356
window[settings.functionName](t.parentNode.id);

Keine Notwendigkeit für eine Auswertung ()

71
Fabien Ménager

Hier ist eine allgemeinere Möglichkeit, das Gleiche zu tun und dabei Bereiche zu unterstützen:

// Get function from string, with or without scopes (by Nicolas Gauthier)
window.getFunctionFromString = function(string)
{
    var scope = window;
    var scopeSplit = string.split('.');
    for (i = 0; i < scopeSplit.length - 1; i++)
    {
        scope = scope[scopeSplit[i]];

        if (scope == undefined) return;
    }

    return scope[scopeSplit[scopeSplit.length - 1]];
}

Hoffe, es kann einigen Leuten helfen.

67
NGauthier

JavaScript hat eine eval Funktion, die einen String auswertet und als Code ausführt:

eval(settings.functionName + '(' + t.parentNode.id + ')');
14
Andrew Hare

eval () ist die Funktion, die Sie dazu benötigen, aber ich würde empfehlen, eines dieser Dinge zu versuchen, um die Verwendung von eval zu minimieren. Hoffentlich ergibt einer von ihnen einen Sinn für Sie.

Funktion speichern

Speichern Sie die Funktion als Funktion, nicht als Zeichenfolge, und verwenden Sie sie später als Funktion. Wo Sie die Funktion tatsächlich speichern, liegt bei Ihnen.

var funcForLater = clickedOnItem;

// later is now
funcForLater(t.parentNode.id);

oder

someObject.funcForLater = clickedOnItem;    
// later is now    
(someObject.funcForLater)(t.parentNode.id);

Funktionsname speichern

Auch wenn Sie den Funktionsnamen als Zeichenfolge speichern müssen, können Sie die Komplexität auf diese Weise minimieren

(eval(settings.functionName))(t.parentNode.id);

dies minimiert die Menge an Javascript, die Sie erstellen und auswerten müssen.

Dictionary of handlers

Fügen Sie alle möglicherweise benötigten Aktionsfunktionen in ein Objekt ein und rufen Sie sie mithilfe der Zeichenfolge im Wörterbuchstil auf.

// global
itemActions = { click: clickedOnItem, rightClick: rightClickedOnItem /* etc */ };

// Later...
var actionName = "click"; // Or wherever you got the action name
var actionToDo = itemActions[actionName];
actionToDo(t.parentNode.id);

(Kleiner Hinweis: Wenn Sie stattdessen hier die Syntax itemActions[actionName](t.parentNode.id); verwenden, wird die Funktion als Methode von itemActions aufgerufen.)

13
Jesse Millikan

Ich mag zwar die erste Antwort und hasse Eval, aber ich möchte hinzufügen, dass es einen anderen Weg gibt (ähnlich wie Eval). Wenn Sie es umgehen und nicht verwenden können, tun Sie es besser. In einigen Fällen möchten Sie möglicherweise einen JavaScript-Code vor oder nach einem Ajax-Aufruf aufrufen. Wenn Sie diesen Code in einem benutzerdefinierten Attribut anstelle von Ajax haben, können Sie Folgendes verwenden:

    var executeBefore = $(el).attr("data-execute-before-ajax");
    if (executeBefore != "") {
        var fn = new Function(executeBefore);
        fn();
    }

Oder speichern Sie dies schließlich in einem Funktionscache, wenn Sie ihn möglicherweise mehrmals aufrufen müssen.

Nochmals - verwenden Sie eval oder diese Methode nicht, wenn Sie eine andere Möglichkeit dazu haben.

9
nsimeonov

Wenn settings.functionName ist bereits eine Funktion, Sie könnten dies tun:

settings.functionName(t.parentNode.id);

Ansonsten sollte dies auch funktionieren, wenn settings.functionName ist nur der Name der Funktion:

if (typeof window[settings.functionName] == "function") {
    window[settings.functionName](t.parentNode.id);
}
8
Gumbo

Ich wollte in der Lage sein, einen Funktionsnamen als Zeichenfolge zu verwenden, ihn aufzurufen UND der Funktion ein Argument zu übergeben. Ich konnte die ausgewählte Antwort für diese Frage nicht bekommen, aber diese Antwort erklärte es genau, und hier ist eine kurze Demo.

function test_function(argument)    {
    alert('This function ' + argument); 
}

functionName = 'test_function';

window[functionName]('works!');

Dies funktioniert auch mit mehreren Argumenten.

7
B Rad C

Es dauerte eine Weile, bis ich herausgefunden hatte, dass die herkömmliche Funktion window['someFunctionName']() für mich zunächst nicht funktionierte. Die Namen meiner Funktionen wurden als AJAX Antwort aus einer Datenbank abgerufen. Aus welchem ​​Grund auch immer, meine Funktionen wurden außerhalb des Bereichs des Fensters deklariert. Um dies zu beheben, musste ich die Funktionen, von denen aus ich sie aufrief, neu schreiben

function someFunctionName() {}

zu

window.someFunctionName = function() {}

und von dort konnte ich window['someFunctionName']() mit Leichtigkeit aufrufen. Ich hoffe das hilft jemandem!

3
illusivefingers

Basierend auf der Antwort von Nicolas Gauthier:

var strng = 'someobj.someCallback';
var data = 'someData';

var func = window;
var funcSplit = strng.split('.');
for(i = 0;i < funcSplit.length;i++){
   //We maybe can check typeof and break the bucle if typeof != function
   func = func[funcSplit[i]];
}
func(data);

Ich bevorzuge es, so etwas zu benutzen:

window.callbackClass['newFunctionName'] = function(data) { console.log(data) };
...
window.callbackClass['newFunctionName'](data);
2
Tom Johnson

In Javascript, das die CommonJS-Spezifikation verwendet, wie zum Beispiel node.js, können Sie das tun, was ich unten zeige. Das ist ziemlich praktisch, um über einen String auf eine Variable zuzugreifen, auch wenn sie nicht für das Objekt window definiert ist. Wenn es eine Klasse mit dem Namen MyClass gibt, die in einem CommonJS-Modul mit dem Namen MyClass.js definiert ist

// MyClass.js
var MyClass = function() {
    // I do stuff in here. Probably return an object
    return {
       foo: "bar"
    }
}

module.exports = MyClass;

Sie können dann dieses nette Stück Hexerei aus einer anderen Datei namens MyOtherFile.js machen

// MyOtherFile.js

var myString = "MyClass";

var MyClass = require('./' + myString);
var obj = new MyClass();

console.log(obj.foo); // returns "bar"

Ein Grund mehr, warum CommonJS so ein Vergnügen ist.

1
nackjicholson