Funktion mit beliebig vielen Parametern aufrufen
greh
- javascript
Ich möchte ein Funktion aufrufen, deren Name ich irgendwoher als String bekomme (als Parameter oder aus der Seite geparst), außerdem habe ich dazu gehörige Parameter, deren Anzahl aber variabel ist. Nun möchte ich die Funktion aufrufen. Da mir bisher nichts besseres eingefallen ist, sieht (verkürzt) das Ergebnis erst mal so aus.
fFunction = eval(sFunction);
switch(aParam.length){
case 1:
fFunction(aParam[0]);
break;
case 2:
fFunction(aParam[0], aParam[1]);
break;
case 3:
fFunction(aParam[0], aParam[1], aParam[2]);
break;
case 4:
fFunction(aParam[0], aParam[1], aParam[2], aParam[3]);
break;
case 5:
fFunction(aParam[0], aParam[1], aParam[2], aParam[3], aParam[4]);
break;
default:
fFunction();
break;
}
Das ganze funktioniert, sieht aber einfach graulich aus und auf 5 Parameter beschränkt. Der eval-Aufruf lässt sich vielleicht noch begründen, da meine Funktion einem Objekt zugehörig sein könnte (sonst auch: window[sFunction]) und ich den Wert tatsächlich als String bekomme.
Im Endeffekt möchte ich einen Funktionsaufruf durchreichen, um ihn bspw. völlig parametrisiert an einen Event zu binden. Was da aufgerufen wird, interessiert mich an dieser Stelle nicht.
Ich möchte also meinen Codeschnipsel passieren können mit den Werten:
var sFunction = "alert";
var aParam = new Array("bin der einzige Parameter");
und ein andermal:
var sFunction = "myObject.ObjextFunktion";
var aParam = new Array("a", "b", new Array(1, 2));
Danke schon mal, greh
Hello,
hilft dir vielleicht die arguments-Eigenschaft der Funktion auf den richtigen Weg? Versuche mal, die Funktion ohne Argumente zu definieren und übergebe trotzdem welche.
MfG
Rouven
Hi,
vielleicht hilfts Dir ja die argumente tuttikompleti rüberzureichen, an eine beliebige function. Also so in der Art quasi:
<script type="text/javascript">
var tues = function(welcheFunktion)
{
thiswelcheFunktion;
}
var eineFunktion = function (v)
{
for (i=1;i<v.length;i++)
{
alert('ich '+v[i]);
}
}
var andereFunktion = function (v)
{
for (i=1;i<v.length;i++)
{
alert('und du '+v[i]);
}
}
</script>
<a href="#" onClick="tues('eineFunktion','mach dies');return false">los</a>
<a href="#" onClick="tues('andereFunktion','machst das','machst jenes','machst auch das noch');return false">jetzt</a>
Gute Nacht
Marcel
hilft dir vielleicht die arguments-Eigenschaft der Funktion auf den richtigen Weg? Versuche mal, die Funktion ohne Argumente zu definieren und übergebe trotzdem welche.
ich hatte darüber nachgedacht, brachte mich aber nicht weiter. Das Problem ist, dass ich möglichst meine aufzurufende Funktion nicht kennen müssen sollte.
greh
Im Endeffekt möchte ich einen Funktionsaufruf durchreichen, um ihn bspw. völlig parametrisiert an einen Event zu binden. Was da aufgerufen wird, interessiert mich an dieser Stelle nicht.
Da gibt es mehrere Möglichkeiten, kommt darauf an wie das ganze konkret aussieht.
Struppi.
Da gibt es mehrere Möglichkeiten, kommt darauf an wie das ganze konkret aussieht.
Struppi.
Ok, folgende Konstellation:
ich habe ein seitenspezifisches Array folgender Art
var aEventList = new Array();
aEventList[1] = new Array();
aEventList[1][event] = "blur";
aEventList[1][elementid] = "field1";
aEventList[1][function] = "alert";
aEventList[1][param] = new Array("bin der einzige Parameter");
aEventList[2] = new Array();
aEventList[2][event] = "click";
aEventList[2][elementid] = "link5";
aEventList[2][function] = "myObject.ObjextFunktion";
aEventList[2][param] = new Array("a", "b", new Array(1, 2));
Dann brauche ich also noch eine globale Init-Function, die meine Event-Handler setzt, auf die Schnelle vielleicht so (mit prototype.js-Unterstützung):
function init(){
for(var i=0; i< aEventList.length; i++){
Event.observe($(aEventList[i][elementid]), aEventList[i][event], function(event){ observe(event, aEventList[i][function], aEventList[i][param]); }, false);
}
}
function observe(oEvent, sFunction, aParam){
// hier jetzt der schon gepostete Quelltext
}
Dem aufmerksamen Beobachter wird sicher auffallen, dass sFunction und aParam in der Funktion observe nicht richtig ankommen, wenn das unter einem Event-Kontext aufgerufen wird. Das Problem habe ich gelöst, die Funktionen init und observe befinden sich in einem Objekt und die Parameter sind als Objektvariablen gespeichert. Für das Beispiel eigentlich nicht relevant.
Die Idee dürfte klar sein. Ich möchte eine Liste mit abarbeitbaren Event-Initialisierungen haben.
Ok, folgende Konstellation:
Bevor ich mich ausführlich damit auseinandersetze, bleibt die Frage:
aEventList[2][function] = "myObject.ObjextFunktion";
Was ist myObject?
Ohne die Information läßt sich immer noch kein Lösungsweg entwickeln.
Struppi.
Was ist myObject?
Ohne die Information läßt sich immer noch kein Lösungsweg entwickeln.
Ein beliebiges Objekt, genau das will ich ja möglichst nicht wissen. Es könnte bspw. folgender Art sein:
var myObject = {
sName : "myObjekt",
ObjextFunktion : function(sParam1, sParam2, aParam3){
alert("ObjextFunktion in "+myObject.sName+" hätte gerne ein Array als dritten Parameter.");
}
}
Vielleicht sind sParam1 und sParam2 die Element-ID von Fomularfeldern. Wird nun das Feld mit ID sParam1 etwas eingegeben, möchte ich im Feld 'sParam2' eine Auswahlliste haben, deren Werte durch aParam3 definiert sind.
Ich möchte mir also für kommende Probleme solcherart Objekte (oder globale Funktionen) schaffen können, die ich dann mit einem Eventhandler verbinden kann und irgend welche Jobs machen. Nur möchte ich die Eventhandlerdefinition nicht im Quelltext der HTML-Ausgabe haben, sondern zentral.
Das Ganze könnte man vielleicht als Schnittstelle für Ereignisbedingte Funktionen verstehen.
greh
Was ist myObject?
Ohne die Information läßt sich immer noch kein Lösungsweg entwickeln.Ein beliebiges Objekt, genau das will ich ja möglichst nicht wissen. Es könnte bspw. folgender Art sein:
var myObject = {
sName : "myObjekt",
Das ist genau die Frage, soll myObjekt und "myObjekt" identisch sein, denn dann ist myObjekt in der Objektfunktion this. D.h. du brauchst weder den Namen der variabel noch die ID des Elementes.
Struppi.
Was ist myObject?
Ohne die Information läßt sich immer noch kein Lösungsweg entwickeln.Ein beliebiges Objekt, genau das will ich ja möglichst nicht wissen. Es könnte bspw. folgender Art sein:
var myObject = {
sName : "myObjekt",Das ist genau die Frage, soll myObjekt und "myObjekt" identisch sein, denn dann ist myObjekt in der Objektfunktion this. D.h. du brauchst weder den Namen der variabel noch die ID des Elementes.
Gemeint war es nicht so, myObject.sName sollte nur den Namen des Objektes speichern. Aber auch, wenn ich eine Objektvariable hätte:
var myObject = {
sName : "myObjekt",
oThis : this,
...
Abgesehen vom Problem, dass ich die Funktion über den Eventhandler aufrufe, also this dann auf das Window-Objekt zeigen müsste (das dürfte sich durch ein Closure lösen lassen):
Bringt mich das bei meinem Problem weiter? Oder habe ich das gerade nicht ausreichend verstanden?
greh
Abgesehen vom Problem, dass ich die Funktion über den Eventhandler aufrufe, also this dann auf das Window-Objekt zeigen müsste (das dürfte sich durch ein Closure lösen lassen):
Jein, du kannst ein lokale Referenz auf das aktuelle Objekt erstellen, die dann in deiner closure Funktion benutzt wird. Allerdings ist es schwierig zu sagen wie genau das aussieht, da du ja in deinem Beispiel ein allgemeines Objekt erstellst und kein Funktionsobjekt, das noch mehr Möglichkeiten bieten würde.
wie schon gesagt, es gibt für das was du willst mehrere Wege, nur welcher läßt sich nicht konkret sagen mit konkreten Angaben.
Um das mal etwas genauer zu beschreiben ein Beispiel wie man Eventhandler in einem Objekt benutzen kann.
function myObj(id) {
var o = document.getElementById(id);
var self = this;
// private Funktion
var myMouseover = function() { o.style.color = 'red';};
// public Funktion
this.click = function(e) { o.style.color = '';};
// Eventhandler
o.onclick = function(e) { self.click(e);};
o.onmousover = function(e) { myMouseOver();};
}
(ungetestet und ohne Fehlerabfrage)
Struppi.
Abgesehen vom Problem, dass ich die Funktion über den Eventhandler aufrufe, also this dann auf das Window-Objekt zeigen müsste (das dürfte sich durch ein Closure lösen lassen):
Jein, du kannst ein lokale Referenz auf das aktuelle Objekt erstellen, die dann in deiner closure Funktion benutzt wird. Allerdings ist es schwierig zu sagen wie genau das aussieht, da du ja in deinem Beispiel ein allgemeines Objekt erstellst und kein Funktionsobjekt, das noch mehr Möglichkeiten bieten würde.
wie schon gesagt, es gibt für das was du willst mehrere Wege, nur welcher läßt sich nicht konkret sagen mit konkreten Angaben.
Um das mal etwas genauer zu beschreiben ein Beispiel wie man Eventhandler in einem Objekt benutzen kann.
function myObj(id) {
var o = document.getElementById(id);
var self = this;
// private Funktion
var myMouseover = function() { o.style.color = 'red';};
// public Funktion
this.click = function(e) { o.style.color = '';};
// Eventhandler
o.onclick = function(e) { self.click(e);};
o.onmousover = function(e) { myMouseOver();};}
> (ungetestet und ohne Fehlerabfrage)
Ja, ich denke, den Ansatz zu verstehen. Dein Objekt beinhaltet das Element, das Ereignis und die dann auszuführende Funktionalität. Natürlich möchte in meinem speziellen Objekt im Wesentlichen nur die Funktionalität definieren. Die Verbindung zum Ereignis und zum Element soll zentral definiert sein.
Um also aus einem zentralen Array ein solches Objekt zu gewinnen, könnte man sich etwas schaffen, welches aus einem abstraktes Objekt, den Parametern und der irgendwo definierten Funktion ein Objekt ähnlich deinem liefert, also Ereignis, Element und Funktionalität verbindet. Die Funktionsparameter sind dann in diesem Objekt gespeichert wie auch die speziell gestrickte Funktion.
Tatsächlich wäre mein nächster Schritt der Recherche in genau diese Richtung gegangen. Allerdings steht davor noch die genaue Auseinandersetzung mit prototypischer Vererbunug. Das schaffe ich vielleicht über die weihnachtlichen Tage.
Noch nicht klar ist mir, wie ich trotz diesen schon mal sinnvollen Ansatzes in meinem Objekt die ...
Egal. Das muss ich mir erst noch überlegen und etwas experimentieren. Soweit schon mal schönen Dank,
greh
Ja, ich denke, den Ansatz zu verstehen. Dein Objekt beinhaltet das Element, das Ereignis und die dann auszuführende Funktionalität. Natürlich möchte in meinem speziellen Objekt im Wesentlichen nur die Funktionalität definieren. Die Verbindung zum Ereignis und zum Element soll zentral definiert sein.
Da könnte wiederum .apply() in's Spiel kommen.
function myObj(id) {
var o = document.getElementById(id);
var self = this;
// private Funktion
var myMouseover = function() { o.style.backgroundColor = 'red';};
// public Funktion
this.click = function(e) { o.style.backgroundColor = '';};
// Eventhandler
EventHandler.apply(o, [this.click, myMouseover]);
}
function EventHandler(click, over){
this.onclick = function(e) { click(e);};
this.onmouseover = function(e) { over(e);};
}
Tatsächlich wäre mein nächster Schritt der Recherche in genau diese Richtung gegangen. Allerdings steht davor noch die genaue Auseinandersetzung mit prototypischer Vererbunug. Das schaffe ich vielleicht über die weihnachtlichen Tage.
Wobei ich sagen muss dass die mir nicht gefällt, dort treten Nebeneffekte auf, die du anderswo nicht hast. Momentan behelfe ich mich, wenn ich vererben will, in dem ich diesen Ansatz benutze. (Die Seiten von Douglas Crockford sind absolut lesenswert, um in die Geheimnisse von OOP in JS einzutauchen)
Noch nicht klar ist mir, wie ich trotz diesen schon mal sinnvollen Ansatzes in meinem Objekt die ...
Das ist die Frage, was du konkret willst.
Egal. Das muss ich mir erst noch überlegen und etwas experimentieren. Soweit schon mal schönen Dank,
Keine Problem, genauso mach ich es auch immer ;-)
Struppi.
gruss greh,
Im Endeffekt möchte ich einen Funktionsaufruf durchreichen, um ihn
bspw. völlig parametrisiert an einen Event zu binden. Was da aufgerufen
wird, interessiert mich an dieser Stelle nicht.Ich möchte also meinen Codeschnipsel passieren können mit den Werten:
var sFunction = "alert";
var aParam = new Array("bin der einzige Parameter");und ein andermal:
var sFunction = "myObject.ObjextFunktion";
var aParam = new Array("a", "b", new Array(1, 2));
zum *durchschleifen* von argumentenlisten(argumentenarrays) bietet sich
»[Function].apply« an.
entweder frisch drauflos:
var sFunction = "alert";
var aParam = new Array("bin der einzige Parameter");
window[sFunction].apply(null, aParam);
oder aber zurueckhaltender:
var sFunction = "alert";
var aParam = new Array("bin der einzige Parameter");
var fFunction = window[sFunction];
if (fFunction && (typeof fFunction.apply == "function") && (aParam instanceof Array)) {
fFunction.apply(null, aParam);
}
so long - peterS. - pseliger@gmx.net
zum *durchschleifen* von argumentenlisten(argumentenarrays) bietet sich
»[Function.apply«] an.
Danke.
Ja, das scheint mir der passende Ansatz zu sein. Ich werde mir das mal genauer ansehen. Interessant finde ich die Frage, ob ich so etwas wie diese Apply-Funktion selbst zusammenbauen könnte unter der Voraussetzung, dass ich die aufzurufende Funktion nicht kenne.
In Perl wäre es trivial, aber das ist eine andere Geschichte.
greh
zum *durchschleifen* von argumentenlisten(argumentenarrays) bietet sich
»[Function.apply«] an.Danke.
wie ich schon gesagt habe, es gibt mehrere Möglichkeiten, das ist eine. aber so wie du es beschrieben hast, brauchst du diesen Weg nicht, nur müßte man man da mehr wissen. Aber du möchtest nicht mehr Preis geben?
Struppi.
wie ich schon gesagt habe, es gibt mehrere Möglichkeiten, das ist eine. aber so wie du es beschrieben hast, brauchst du diesen Weg nicht, nur müßte man man da mehr wissen. Aber du möchtest nicht mehr Preis geben?
Nein, ich möchte es nur nicht unnötig kompliziert machen. Deswegen muss ich meinen Beispielcode erst etwas aufbereiten. Folgt in Kürze,
greh