Wie Variable als Argument einer Funktion übergeben?
Helgor
- javascript
Hallo, ich versuche gerade, eine rekursive Funktion (hier rinseNrepeat
) zu schreiben, die ich möglichst allgemein halten will, damit ich sie
mehrmals flexibel einsetzen kann (und so unnötige Redundanzen vermeide).
Diese Funktion beinhaltet nun leider ein setTimeout, welches von außerhalb der Funktion wieder geclear
ed werden
soll, hier exemplarisch auf button
click
. Dazu muss ich das Timeout in einer von außerhalb des Funktionsscope zugänglichen Variable speichern (damit der Button Zugriff hat).
Wenn ich die setTimeout-Variable aber innerhalb der Funktion hardcode, so ist diese nicht mehr flexibel gehalten und allgemein überall verwendbar,
daher wollte ich die Variable, in der das setTimeout gespeichert wird, als Argument der Funktion übergeben. Dazu definiere ich zuerst ein Objekt (hier: varSammelobjekt
).
In diesem Objekt will ich nun die Timeouts speichern, nach dem Schema
varSammelobjekt = {
Timeout1: setTimeout(rinseNrepeat, 1000),
// etc.
};
Das funktioniert leider nicht so, wie ich mir das vorstelle. Was mache ich falsch, wie mache ich's richtig?
Der Kot:
const stopDenWahnsinn = document.getElementById("stopDenWahnsinn"); // im DOM ein Button mit dieser ID
let varSammelobjekt = {};
function rinseNrepeat(timeoutVar) {
console.log("Hallo aus Funktion");
// Weiterer Code
timeoutVar = setTimeout(rinseNrepeat, 1000);
}
rinseNrepeat(varSammelobjekt["Timeout1"]);
stopDenWahnsinn.addEventListener("click", () => {
clearTimeout(varSammelobjekt["Timeout1"]);
// tut nix X(
});
Dank euch mit Herzlichkeit
Hallo,
hab das Debakel doch selbst gelöst...
Des Pudels Kern: natürlich kennt die rinseNrepeat Funktion die Parameter nicht mehr, wenn das Timeout sie ohne Parameter aufruft 🤦♂️
Dank trotzdem
Hallo Helgor,
nein, so macht man das nicht. Das Sammelobjekt ist ja auch wieder global. Damit verlagerst Du nur das Problem von der Timeout-Variablen auf das Sammelobjekt.
Die Idee ist, eine Closure zu benutzen (Erklärungen im SelfWiki).
Und eigentlich möchtest Du doch setInterval verwenden, um setTimeout nicht immer wieder neu aufrufen zu müssen, oder?
function runRinseNRepeat(stopButton) {
const intervalTimer = setInterval(rubRubDubDub, 1000);
stopButton.addEventListener("click",
() => {
console.log("Clean!!!");
clearInterval(intervalTimer);
});
function rubRubDubDub() {
console.log("With a rub rub rub and a dub dub dub in the water in the water...");
// do Work
}
}
// somewhere else
runRinseNRepeat(document.getElementById("stopDenWahnsinn"));
Die vom Click-Handler und von rubRubDubDub gebildeten Closures teilen sich den Scope von runRinseNRepeat und können damit auch nach Ende dieses Funktionsaufrufs darauf zugreifen.
Je nachdem, wie dein übriger Code aussieht, reicht das hin. Aber wenn runRinseNRepeat nun eine globale Funktion ist, dann ist das Problem, den globalen Fußabdruck zu vermeiden, immer noch nicht gelöst. Das geht aber, und zwar, wenn Du runRinseNRepeat zu einer IIFE machst:
(function(stopButton) {
const intervalTimer = setInterval(rubRubDubDub, 1000);
stopButton.addEventListener("click", () => {
console.log("Clean!!!");
clearInterval(intervalTimer);
});
function rubRubDubDub() {
console.log("With a rub rub rub and a dub dub dub in the water in the water...");
// do Work
}
})(document.getElememtById("stopDenWahnsinn"));
Ob Du document.getElememtById("stopDenWahnsinn")
nun als Parameter in die IIFE hineingibst oder es drinnen direkt einbaust, ist Geschmackssache oder mag auch an anderen Rahmenbedingungen hängen. Du kannst auch nur die ID hineingeben.
Natürlich kannst Du das, wenn Du es unbedingt willst, auch mit setTimeout lösen. In rubRubDubDub ist die intervalTimer-Variable genauso verfügbar. Du musst dann nur let statt const verwenden...
Rolf