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
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);
}
window[settings.functionName](t.parentNode.id);
Keine Notwendigkeit für eine Auswertung ()
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.
JavaScript hat eine eval
Funktion, die einen String auswertet und als Code ausführt:
eval(settings.functionName + '(' + t.parentNode.id + ')');
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.)
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.
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);
}
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.
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!
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);
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.