Klaus1: wie Zugriff auf Javascript-Funktion?

Hallo,

auf einer Webseite gibt es mehrere <script>-Bereiche.

Ein Script-Teil befindet sich im <head>-Teil und einen weiteren, der im Body-Teil wie folgt aufgebaut ist:

			<script>
				window.onload = function () {


					var myobj = new MyObject(document.getElementById("baum"), {
					});


					function save() {
					}
				};
			</script>

Im JS vom Head-Teil wird ein Ajax-Script aufgerufen, dass Daten zurückliefert, die ich der Funktion (save) innerhalb des Body-Teils übergeben muss. Oder ich muss auf ein dort erstelltes Objekt (myobj) zugreifen können.

Habt ihr da eine Idee, wie ich das bewerkstelligen könnte?

LG Klaus

  1. Tach!

    Habt ihr da eine Idee, wie ich das bewerkstelligen könnte?

    Da in getrennten Script-Bereiencn kein gemeinsamer Scope anzulegen geht, wüsste ich grad nicht, was da noch möglich wäre, außer Referenzen für die benötigten Dinge im globalen Scope (sprich: window) anzulegen.

    dedlfix.

  2. Lieber Klaus1,

    			<script>
    				window.onload = function () {
    ...
    				};
    			</script>
    

    warum sich auf diese Uralt-Methode verlassen? Sie hat nicht umsonst ausgedient.

    Im JS vom Head-Teil wird ein Ajax-Script aufgerufen, dass Daten zurückliefert, die ich der Funktion (save) innerhalb des Body-Teils übergeben muss.

    In solchen Fällen benötigst Du eine "globale Variable", also eine dem window-Objekt (oder dem document-Objekt) hinzugefügte Eigenschaft wie etwa window.myData. Das will man aber "richtig" machen, da solche "globalen Variablen" in aller Regel unsaubere Programmierung sind. Besser ist ein globales Objekt, welches Deine Geschäftslogik und Daten kapselt:

    // Code ungetestet!
    window.myApplication = {
      MyObject: (element, data) => {
        // ...
      },
      "andere Eigenschaft": 42,
      "andere Methode": (param) => {
        // ...
      },
      ajaxData: {},
      baum: null,
      save: () => {
        // tue etwas
        console.log(this.ajaxData);
      },
      setup: () => {
        // initialisiere Baum
        this.baum = new this.MyObject(
          document.getElementById("baum"),
          {}
        );
      }
    };
    
    document.addEventListener(
      "DOMContentLoaded",
      (event) => { myApplication.setup(); }
    );
    

    Auf diese Weise hast Du alles für Deine Applikation gekapselt und kannst aus anderen Geltungsbereichen heraus darauf zugreifen.

    Oder ich muss auf ein dort erstelltes Objekt (myobj) zugreifen können.

    Ja, in der oben beschriebenen Art und Weise.

    Liebe Grüße

    Felix Riesterer

    1. Hallo Felix

      window.myApplication = {
        MyObject: (element, data) => {
          // ...
        }
      };
      

      So funktioniert das nicht. Pfeilfunktionen können nicht als Konstruktor verwendet werden. Du müsstest stattdessen entweder einen gewöhnlichen Funktionsausdruck verwenden oder einen Klassenausdruck.

      window.myApplication = {
          MyObject: class {
              constructor(element, data) {
                  // ...
              }
          }
      };
      

      Pfeilfunktionen besitzen gar keine Bindung für this. Wenn du innerhalb einer Pfeilfunktion auf this zugreifst, wird der Wert der Variable im umgebenden Scope zurückgegeben.

        ajaxData: {},
        save: () => {
          console.log(this.ajaxData);
        }
      

      Das hier wird dir also undefined in die Konsole schreiben, da this außerhalb der Funktion eine Referenz auf Window enthält und Window keine Eigenschaft mit diesem Namen besitzt.


      Besonders zu beachten ist dabei, dass du bei einem Aufruf dieser Methode keine Fehlermeldung bekommen würdest, selbst dann, wenn du das Skript im strict mode ausführst.

      'use strict';
      
      function f() {
          return this.x;
      }
      
      f();
      

      Das gibt einen Typfehler, weil diese Funktion ein eigenes this besitzt, das im strikten Modus außerhalb eines Konstruktoraufrufs undefined ist.

      'use strict';
      
      const object = {
          f: () => {
              return this.x;
          }
      };
      
      object.f();
      

      Das gibt keinen Fehler, weil this über die scope chain zu Window aufgelöst wird.


      Wenn du innerhalb einer Methode über this auf das Kontextobjekt zugreifen möchtest, kannst du die Syntax für Methodendefinitionen verwenden:

          ajaxData: {},
          save() {
              console.log(this.ajaxData);
          }
      

      Viele Grüße,

      Orlok

      1. Lieber Orlok,

        vielen Dank für Deine Berichtigung. Hätte ich das alles besser "oldschool" mit dem Schlüsselwort function geschrieben, hätte das gepasst.

        Liebe Grüße

        Felix Riesterer

      2. Servus!

        Schön, mal wieder von Dir zu hören!

        Herzliche Grüße

        Matthias Scharwies

        --
        Einfach mal was von der ToDo-Liste auf die Was-Solls-Liste setzen.“
  3. Im JS vom Head-Teil wird ein Ajax-Script aufgerufen, dass Daten zurückliefert, die ich der Funktion (save) innerhalb des Body-Teils übergeben muss. Oder ich muss auf ein dort erstelltes Objekt (myobj) zugreifen können.

    Habt ihr da eine Idee, wie ich das bewerkstelligen könnte?

    Falls du globale Variablen vermeiden möchtest, könntest du auch mit einem CustomEvent arbeiten.

    Im Kopfteil kannst du im ready-Callback der AJAX-Anfrage ein CustomEvent erzeugen und auslösen:

    fetch('https://example.com').then(response => {
      const myEvent = new CustomEvent('myCustomEvent', {detail: response})
      document.dispatchEvent(myEvent)
    })
    

    Im Bodyteil kannst du einen Event-Listener registrieren und auf das Event reagieren:

    document.addEventListener('myCustomEvent', event => {
       const response = event.detail;
       // Mach etwas mit dem Response
    })
    

    Der Code ist ungetestet, er soll nur das Prinzip verdeutlichen.

  4. Hallo,

    vielen Dank an alle Antworter, ihr habt mir sehr weitergeholfen. Ich habe mich eines kleinen Tricks bedient, indem ich ein Hidden-Feld im Body-Bereich erstellt habe, auf dem ich ein onChange-Event gelegt habe, dass dann meine Funktion aufruft. Im Head-Script hole ich mir dann das Input-Element, befülle es und feuere dann das Change-Event.

    LG Klaus