bobby: jQuery Variablenübergabe (mal wieder)

Moin,

Ich hab immer ganz spezielle Probleme:


// irgendwo im JS: 
var elem=$('#einElement');

// dann an anderer Stelle
.post(url,{'value':elem.val(),'class':elem.attr('class'),'name':elem.attr('name')},function(e){
     console.info(elem)
}).fail(function(e){
     console.info(elem)
            }).always(function(){
     console.info(elem)
            }).done(function(){
     console.info(elem)
            });

elem ist immer Null außer in den Parametern, die Post sendet. Wie bekomm ich das Elem an die jeweiligen Funktionen übergeben? Und ja, elem ist global

Gruß Bobby

--
-> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
  1. Moin,

    Hat sich erledigt. Ich setzte die Variable unter der $.POST Funktion null und hab wieder die Asynchronität nicht beachtet.

    Ist es so dass das Ausschalten der Asynchronität auf deprecated gesetzt ist?

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
    1. Tach!

      Ist es so dass das Ausschalten der Asynchronität auf deprecated gesetzt ist?

      Was bitte? Synchron ist nicht toll, weil dann deine Anwendung einfriert. Gewöhn dich lieber daran, dass die Dinge mitunter in anderer Reihenfolge aufgerufen werden, als sie in deinem Code stehen. Da führt kein Weg vorbei. Für Aufräumarbeiten, die nach den Aufrufen der Callbacks erst stattfinden dürfen, gibt es ja die always-Methode vom jqHXR-Promise.

      dedlfix.

  2. Lieber bobby,

    Und ja, elem ist global

    das wird das Problem sein. Du machst mit elem an anderer Stelle etwas, was dann in den gekapselten Funktionen (den "closures") den Variableninhalt verändert, sodass bei deren Ausführung kein vernünftiger Inhalt mehr zur Verfügung steht.

    Warum muss elem global sein?

    Im Notfall könntest Du "mit Gewalt" eine Funktion basteln, in der der Inhalt von elem an eine andere und nur in dieser Funktion vorhandene Variable übergeben wird:

    var elem = $("#elem");
    
    // wir bauen uns eine gleich ausgeführte Funktion
    [elem].forEach(function (_elem) {
        // _elem ist nun "gegen außen geschützt"
        tuWas(_elem);
    });
    
    // wir bauen uns noch eine Funktion...
    function (_elem) {
        // _elem ist nun "gegen außen geschützt"
        tuWas(_elem);
    
    }(elem); // ... und führen sie gleich aus (mit Parameter)
    

    Wie Du das machst, ist mir egal. Am besten wird der Verzicht auf globale Variablen sein. Vielleicht kannst Du sogar Objekte definieren, die Daten bereithalten und die Logik Deiner Applikation abbilden?

    Liebe Grüße,

    Felix Riesterer.

    1. Moin,

      Warum muss elem global sein?

      Wegen der zeitlichen Diskrepanz zwischen Ausführung und Benutzung. Ich speichere ein Element zwischen, was ich innerhalb der Closures und auch außerhalb verwende. Einmal für CSS-Manipulationen, zum anderen für die Datenauswertung. Warum sollte ich hierfür das Element mehrfach speichern. Dies geht doch immer zu Lasten der Performance. Wie gesagt, es war mein Fehler, dass ich das Element auf NULL gesetzt habe, was gar nicht nötig war.

      var elem = $("#elem");
      
      // wir bauen uns eine gleich ausgeführte Funktion
      [elem].forEach(function (_elem) {
          // _elem ist nun "gegen außen geschützt"
          tuWas(_elem);
      });
      
      // wir bauen uns noch eine Funktion...
      function (_elem) {
          // _elem ist nun "gegen außen geschützt"
          tuWas(_elem);
      
      }(elem); // ... und führen sie gleich aus (mit Parameter)
      

      Trotzalledem ist dies ein sehr interessanter Ansatz. Danke dafür.

      Gruß Bobby

      --
      -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
      1. Tach!

        Warum sollte ich hierfür das Element mehrfach speichern. Dies geht doch immer zu Lasten der Performance.

        Es wird nicht mehrfach gespeichert, nur mehrfach referenziert.

        Mach dir mal keinen allzu großen Kopf über die Performance bei solchen Kleinigkeiten. Eine einzelne Zuweisung einer Referenz auf ein Objekt bringt keinen Browser um. Viel wichtiger ist eine für den Menschen nachvollziehbare Programmierung der Lösung für die Aufgabenstellung.

        Was vor allem spart, ist, Ergebnisse von DOM-Abfragen in Variablen abzulegen, wenn man diese mehrfach braucht, statt das DOM erneut danach zu befragen.

        // mal ganz abgesehen davon, dass man die Methodenaufrufe auch chainen/verketten kann ...
        
        var $foo = $('.foo');
        $foo.text('bar');
        $foo.click(function () {...});
        
        // statt
        
        $('.foo').text('bar');
        $('.foo').click(function () {...});
        

        Nebenbei: Bei jQuery gibt es eine ungeschriebene Konvention, dass man Variablen, die jQuery-Objekte referenzieren, mit einem $ beginnt. Dann weiß man, dass man darauf weitere jQuery-Methoden anwenden kann.

        var $foo = $('#foo'); // jQuery-Objekt
        var foo = $foo[0]; // plain old DOM object

        // wir bauen uns noch eine Funktion...
        function (_elem) {
            // _elem ist nun "gegen außen geschützt"
            tuWas(_elem);
        
        }(elem); // ... und führen sie gleich aus (mit Parameter)
        

        Trotzalledem ist dies ein sehr interessanter Ansatz. Danke dafür.

        Dieser Ansatz nennt sich IIFE (immediately invoked function expression = sofort aufgerufener Funktionsausdruck) und hat üblicherweise noch ein Klammerpaar mehr (vor dem function und nach dem }). Das "gegen außen geschützt" ist so eine Sache. Da Objekte per Referenz übergeben werden, ist nur die Referenz selbst geschützt, nicht aber das Objekt. Das heißt, der Garbage Collector räumt das Objekt nicht weg, weil noch die Referenz in der IIFE darauf verweist (solange da was lebendes drin ist oder darauf referenziert). Aber überall da, wo man eine Referenz auf das Objekt hat, kann man seinen Inhalt ändern, denn der ist nicht "geschützt". Um ihn zu separieren, muss man einen Clone anlegen, der mehr oder weniger tief die Eigenschaften des Objekts und die Ziel-Objekte der von ihm gehaltenen Referenzen kopiert.

        dedlfix.

        1. Moin,

          Was vor allem spart, ist, Ergebnisse von DOM-Abfragen in Variablen abzulegen, wenn man diese mehrfach braucht, statt das DOM erneut danach zu befragen.

          // mal ganz abgesehen davon, dass man die Methodenaufrufe auch chainen/verketten kann ...
          
          var $foo = $('.foo');
          $foo.text('bar');
          $foo.click(function () {...});
          
          // statt
          
          $('.foo').text('bar');
          $('.foo').click(function () {...});
          

          Das mach ich ja jetzt mit meinem elem schon. ;) Es gab halt nur Abfolgeprobleme...

          Nebenbei: Bei jQuery gibt es eine ungeschriebene Konvention, dass man Variablen, die jQuery-Objekte referenzieren, mit einem $ beginnt. Dann weiß man, dass man darauf weitere jQuery-Methoden anwenden kann.

          var $foo = $('#foo'); // jQuery-Objekt
          var foo = $foo[0]; // plain old DOM object

          Oh... OK, werde ich zukünftig beachten

          Dieser Ansatz nennt sich IIFE (immediately invoked function expression = sofort aufgerufener Funktionsausdruck) und hat üblicherweise noch ein Klammerpaar mehr (vor dem function und nach dem }). Das "gegen außen geschützt" ist so eine Sache. Da Objekte per Referenz übergeben werden, ist nur die Referenz selbst geschützt, nicht aber das Objekt. Das heißt, der Garbage Collector räumt das Objekt nicht weg, weil noch die Referenz in der IIFE darauf verweist (solange da was lebendes drin ist oder darauf referenziert). Aber überall da, wo man eine Referenz auf das Objekt hat, kann man seinen Inhalt ändern, denn der ist nicht "geschützt". Um ihn zu separieren, muss man einen Clone anlegen, der mehr oder weniger tief die Eigenschaften des Objekts und die Ziel-Objekte der von ihm gehaltenen Referenzen kopiert.

          Danke für die Ausführungen. Man lernt doch nie aus

          Gruß Bobby

          --
          -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)