Beate Mielke: Funktion ohne Klammern?

auf der Seite "tecb.htm" von SELFHTML wir capture.Events mit einem Beispiel erklärt:

<script language="JavaScript">
  window.captureEvents(Event.KEYPRESS);
  window.onkeypress = Ausgabe;
  function Ausgabe(Ereignis)
  {
   alert("Sie haben die Taste mit dem Wert " + Ereignis.which + " gedrueckt");
   window.captureEvents(Event.KEYPRESS);
   window.onkeypress = Ausgabe;
  }
  </script>

Meine Frage ist, weshalb kann man in der Zeile

window.onKeypress = Ausgabe;

die runden Klammern nach dem Funktionsnamen "Ausgabe" weglassen?

Viele Grüße

Beate Mielke

  1. Hallo Beate

    Meine Frage ist, weshalb kann man in der Zeile
    window.onKeypress = Ausgabe;
    die runden Klammern nach dem Funktionsnamen "Ausgabe" weglassen?

    Das hab ich mich auch gefragt, als ich die entsprechende Doku von Netscape ausgewertet habe. Ich kann es dir leider nicht sagen. Vermutlich wollte man irgendeine Art von Spezialsyntax schaffen, um dem JavaScript-Interpreter klarzumachen, dass es sich bei dieser Sorte um spezielle Event-Handling-Funktionen handelt. Aber nagel mich nicht darauf fest. Vielleicht liegt es auch nur daran, dass der Programmierer von Netscape, der fuer die Implementierung dieser Sache zustaendig war, der Meinung war, dass seine Freundin zu sehr klammert, und deswegen beschloss er, die Klammern wegzulassen bei der Implementierung. Manchmal habe ich bei solchen "Spezialitaeten" jedenfalls den Eindruck, dass solche menschlichen Schicksale dahinter stecken und keine systematischen Ueberlegungen.
    Ich lasse mich aber gerne belehren, falls jemand doch noch andere Gruende kennt ;-)

    viele Gruesse
      Stefan Muenz

    1. Hallo Stefan,

      Das hab ich mich auch gefragt, als ich die entsprechende Doku von Netscape ausgewertet habe.

      Das heißt also, daß man das in dieser Form nicht auf andere Funktionen übertragen kann?

      »»Vielleicht liegt es auch nur daran, ..., dass seine Freundin zu sehr klammert,...

      lol

      Viele Grüße

      Beate Mielke

      1. Hallo Beate,

        Das heißt also, daß man das in dieser Form nicht auf andere Funktionen übertragen kann?

        Nein, meines Wissens muss bei normalen Funktionsaufrufen immer das () hinter dem Funktionsnamen stehen, auch wenn keine Parameter uebergeben werden.

        viele Gruesse
          Stefan Muenz

    2. Das hab ich mich auch gefragt, als ich die entsprechende Doku von Netscape ausgewertet habe.

      Interessant das das gerade inner Netscape-Docu steht ,
      bei Netscape funktioniert nämlich auch mit Klammern
      und sogar mit Parametern , beim IE aber nicht.

      Sehr ungewöhnlich zumindest und wiederspricht eigentlich
      genau den ansonstigen Beobachtungen von wegen Fehlertoleranz
      bei NC und IE :)

      gruss
      Jens

      1. Hi Jens!

        Interessant das das gerade inner Netscape-Docu steht ,
        bei Netscape funktioniert nämlich auch mit Klammern
        und sogar mit Parametern , beim IE aber nicht.

        Bist Du sicher? Ich habe jetzt extra nochmal in der Netscape-Doku (JS1.1) nachgesehen, da findet sich folgender Abschnitt:

        ==== cut ====
        <h2>Calling event handlers explicitly</h2>

        In JavaScript for Navigator 3.0, you can reset an event handler specified by HTML, as shown in the following example.

        <SCRIPT LANGUAGE="JavaScript">
            function fun1() {
               ...
            }
            function fun2() {
               ...
            }
        </SCRIPT>

        <FORM NAME="myForm">
            <INPUT TYPE="button" NAME="myButton" onClick="fun1()">
        </FORM>

        <SCRIPT>
            document.myForm.myButton.onclick=fun2
        </SCRIPT>

        Note that event handlers are function references, so you must assign fun2, not fun2() (the latter calls fun2 and has whatever type and value fun2 returns).
        ==== break ====

        Das ist ja genau das, was ich in <25106.html> geschrieben habe.

        ==== continuation ====
        Also, since the event handler HTML attributes are literal function bodies, you cannot use <INPUT onClick=fun1> in the HTML source to make fun1 the onClick handler for an input; you must call fun1 instead, as in the example.
        ==== break ====

        Meintest Du vielleicht das? Bei den HTML-Attributen handelt es sich um "literal function bodies" (function body ist das, was zwischen { und } steht). Hier kannst Du also gerne irgendwelche Romane schreiben, insbesondere Functionsaufrufe mit Parameteruebergabe. Und hier MUSST Du die Klammern setzen, denn <INPUT onClick=fun1> heisse ja, dass innerhalb einer x-beliebigen Funktion die Zeile
            fun1;       // ohne Klammern --> Funktion wird NICHT aufgerufen
        stehen wuerde, was bedeutet, das die Adresse (Pointer, Referenz) von fun1 abgefragt wird und das Ergebnis gleich weggeworfen wird (weil keiner Variable zugewiesen).

        ==== continuation ====
        Finally, because JavaScript is case-sensitive, you must spell event handler names in lowercase in JavaScript.
        ==== cut ====

        Beate, bitte beachten! Die Eventhandler muessen klein geschrieben werden. (Du hattest onKeypress geschreiben, woraufhin ich das dann auch immer getan habe.)

        Calocybe

        1. Bist Du sicher? Ich habe jetzt extra nochmal in der Netscape-Doku (JS1.1) nachgesehen, da findet sich folgender Abschnitt:

          Ups.. da geht wohl leicht was durcheinander jetzt,
          die eventhandler von Tags gehen natürlich mit
          Parametern und so , nur Zuweisungen wie

          window.onload=setPosition;
          window.onresize=setPosition;

          akzeptiert IE nicht mit Klammern.

          gruss
          Jens

  2. 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

    1. Hallo Calocybe,

      ..., heisst das nicht nur, dass man die Klammern weglassen DARF, sondern dass man sie weglassen MUSS.

      p = Ausgabe;
      Jetzt steht die Adresse der Funktion in p, und obwohl p eine Variable und keine Funktion ist, kann man spaeter mit p(); ... aufrufen.
      So, ich hoffe das war einigermassen verstaendlich, und vor allem, dass ich damit Recht habe.

      Deine Erklärung klingt plausibel, ich glaube das ist tatsächlich die Lösung.
      Ich habe es jetzt auch nochmal getestet:

      Netscape 4.6:
      window.onKeypress  = Ausgabe;          funktioniert!
      window.onKeypress  = Ausgabe();        funktioniert nicht!

      mit IExplorer logischerweise beides nicht.

      Viele Grüße

      Beate Mielke