Nun würde ich es aber gerne "sauber" machen und beliebig viele Paramter zulassen.
Man würde dieses Problem in JavaScript nicht so umsetzen. Das ist keine Lösung, die die Sprachfeatures benutzt. Keine Ajax-Bibliothek arbeitet so.
Erst einmal würde man eine Callback-Funktion übergeben, keinen Funktionsnamen, denn das hat viele Vorteile. Da JavaScript eine funktionale Sprache ist und jede Funktion ein vollwertiges Objekt, übergibt man Referenzen auf Funktionsobjekte. Die müssen nicht notwendig global sein, sondern können irgendwo anders hängen, lokal und sogar ohne Namen (anonym) als Funktionsausdrücke notiert sein. So kann man es vermeiden, fünfhundert globale Funktionen zu notieren, sondern kann mit Kapselung und Namespaces arbeiten.
Jetzt ist die Frage, wie man diesen Callback-Funktionen gewisse Variablen zur Verfügung stellt. Auch hier würde ich zu einer funktionale Lösung raten. JavaScript bietet Closures, d.h. verschachtelte Funktionen »erinnern« sich an die lokalen Variablen der Funktion, in der sie notiert wurden:
function request (p1, p2, p3) {
var a = 1, b = 2, c = 3;
ajax('/file.txt', function (response) {
/* Closure, schließt p1, p2, p3, a, b und c ein */
alert(response + "\n" + a + "\n" + b + "\n" + c);
});
}
Wenn du es etwas geordneter willst, kannst du mit Currying arbeiten. Dann kann die Verschachtelung wegfallen:
function handler (a, b, c, response) {
alert(response + "\n" + a + "\n" + b + "\n" + c);
}
function request () {
var a = 1, b = 2, c = 3;
ajax('/file.txt', handler.curry(a, b, c));
}
Dazu bräuchtest du diese Helferfunktion, die alle Funktionsobjekte um die Methode curry erweitert:
Function.prototype.curry = (function (slice) {
return function () {
var func = this, args = slice.apply(arguments);
return function () {
return func.apply(this, args.concat(slice.apply(arguments)));
};
};
})(Array.prototype.slice);
Bei dieser Standard-Currying-Funktion wird der Parameter response hinten drangehangen - man könnte ihn auch vorne anhängen (statt concat die arguments-Liste von hinten durchlaufen und alle Elemente mit unshift in args einfügen).
So wäre es meiner Meinung nach »sauber« - deine gegenwärtige Lösung fühlt sich eher nach PHP an (< 5.3 ;-)).
apply und arguments sind auf jeden Fall die Objekte, die dir hier weiterhelfen. Damit könntest du dein Problem auch lösen, ohne die vorgeschlagenen Änderungen vorzunehmen.
// Wandle arguments-Objekt in einen Array um und extrahiere die Parameter 3-n
var args = Array.prototype.slice.call(arguments, 2);
// Füge vorne einen Parameter ein, nämlich den responseText
args.unshift(tmp_ajax_obj.responseText);
// Rufe Funktion auf mit dem erzeugten Array als Parameterliste
window[func_target].apply(window, args);
Das »Durchreichen« der Parameter funktioniert hier ähnlich wie beim Currying.
Mathias