Hallo Beate und Stefan!
Meine Frage ist, weshalb kann man in der Zeile
window.onKeypress = Ausgabe;
die runden Klammern nach dem Funktionsnamen "Ausgabe" weglassen?
Tja, wie soll man das jetzt erklaeren? Ich lege einfach mal die Programmiersprache C zugrunde, auf der JavaScript zu grossen Teilen ja basiert und daher sehr, sehr aehnliche Konzepte hat. Was ich jetzt schreibe, habe ich nicht ueberprueft, also lest das bitte mit Vorbehalt! Nun ja, ich verlasse mich da einfach mal wieder auf die Verwandtschaft von JS und C, das hat schon bei mehreren meiner Beitraege geklappt. Falls ich Recht habe, heisst das (mit einigermassen hoher Wahrscheinlichkeit) nicht nur, dass man die Klammern weglassen DARF, sondern dass man sie weglassen MUSS. Jetzt aber los!
Ein C-Compiler erkennt an den Klammern, dass er eine Funktion AUFRUFEN soll. Man kann den Namen der Funktion auch einfach so hinschreiben, also ohne Klammern, er weiss dann auch, dass es sich um eine Funktion handelt (um das zu erkennen, braucht er die Klammern also nicht), aber er ruft sie trotzdem nicht auf. Vielmehr ermittelt er einen Pointer auf die Funktion, also (vereinfacht gesagt) die Adresse innerhalb der RAM-Bausteine des Computers, an der der Maschinencode der Funktion steht. Was nuetzt einem das? Nun, wenn man eine Variable vom Typ "Zeiger auf eine Funktion" deklariert[1], nennen wir sie p, so kann man diesen Pointer darin speichern. So naemlich:
p = Ausgabe;
Jetzt steht die Adresse der Funktion in p, und obwohl p eine Variable und keine Funktion ist, kann man spaeter mit
p();
die Funktion aufrufen. Die Ausfuehrung des Programms wird also an der Speicheradresse fortgesetzt, die in p steht.
[1] Die Syntax fuer das Deklarieren einer solchen Variable in C erspare ich Euch lieber, die ist naemlich komplett hirnverbrannt! Aber das Problem hat man ja in JS sowieso nicht, da hier Variablen nicht typisiert sind, zumindest nicht sichtbar.
Ja toll, und was soll jetzt das ganze? Na mit der Zeile
window.onKeypress = Ausgabe;
haben wir doch einen ganz tollen Anwendungsfall, der kein ausgedachtes, praxisfernes Beispiel ist! onKeypress ist eine Eigenschaft des window-Objektes, die genau solch einen Pointer darstellt. Und hier hinein wird jetzt die Adresse der (unter JS sagt man wohl besser "eine Referenz auf die") Ausgabe-Funktion geschrieben. Tritt jetzt der Event auf, wird einfach soetwas wie
window.onKeypress();
gemacht, also die Funktion aufgerufen, auf die window.onKeypress "zeigt" (pointet). Tja, das war's eigentlich schon. :-)
Na gut, aber was passiert jetzt, wenn man
window.onKeypress = Ausgabe();
schreibt? Tja, weiss ich natuerlich nicht, weil ich's nicht ausprobiert habe, aber theoretisch wird die Funktion AUFGERUFEN (stehen ja schliesslich Klammern dahinter) und der RUECKGABEWERT der Funktion an onKeypress zugewiesen (naja, das kennen wir ja schon). Ein C-Compiler wuerde an dieser Stelle eine Fehlermeldung ausgeben, weil z.B. eine Zahl (je nachdem was Ausgabe() zurueckgibt) an eine Pointervariable zugewiesen werden soll, was einen Typenkonflikt darstellt. Aber da JS ja keine Typenunterscheidung macht (angeblich jedenfalls, intern machen sie sie doch, was zu sehr wundersamen Effekten fuehren kann; hatten wir auch schon mal nen Thread dazu), sollte er wohl nicht meckern. Dann sollte aber trotzdem das Script nicht funktionieren, da in window.onKeypress nicht der Zeiger auf die Funktion steht. Es waere aber moeglich, dass es trotzdem funktioniert; das hiesse dann, das der JS-Interpreter nicht etwa allgemeingueltig geschrieben wurde, sondern so, dass er geradeso tut, was er soll. Konkret meine ich, dass die Klammern egal waeren, weil der Interpreter sagt, window.onKeypress will einen Funktionspointer haben, also kriegt es einen, egal ob die Syntax stimmt oder nicht.
So, ich hoffe das war einigermassen verstaendlich, und vor allem, dass ich damit Recht habe (wie gesagt, alles unter Vorbehalt!). Also dann...
Calocybe