mb: mehrere ezeugte Object des selben konstruktors steuern

Schönen Guten Abend,

mit dem von mir geskripteten Konstruktor läuft alles wie geschmiert, jedoch nur beim ersten erzeugten Object :/. mehrere ezeugte Objekte vom selben konstruktor lässt sich immer das letzte ansteuern. ich hab z.b. mit window.onresize die Objekte initiieren lassen.

Ich hab immer schön "this" bezogen auf variable sowie public Objektfunktionen aber auch private Objektfunktionen mit "that" und variablen mit "var" usw.

Ich verwende Konstruktor funktion das erste mal und ich könnte auch das new weg lassen dann wäre es ne sible funktion und würde funktionieren aber nur beim letzten Objekt :/.

Habe ich da was net mit bekommen? Soll das so sein? Oder unterlief mir banaler fehler? Schönen abend MB

  1. Lieber mb,

    meine Glaskugel sagt mir, dass Du beim Schreiben der entsprechenden Code-Zeilen die völlig falsche Musik dazu gehört hast. Deswegen haben sich metaphysische Schwingungen entwickelt, die die Datenstruktur Deines Browsers durcheinander bringen, weshalb Du nur noch das zuletzt instantiierte Objekt benutzen kannst.

    Nee, im Ernst: Du machst anscheinend in Deiner Konstruktor-Funktion irgend etwas mit globalen Variablen, oder Du speicherst das Ergebnis dieser mit "new" als Schlüsselwort genutzten Funktion nicht korrekt ab. Hier ein Beispiel:

    function Car (features) {
        this.color = "grey"; // default
    
        if (features && features.blue) {
            this.color = features.color;
        }
    
        this.model = "Trabant"; // default
    
        if (features && features.model) {
            this.model = features.model;
        }
    
        this.engine = {
            energy: "1kW", // default
            health: 100,
            status: "off"
        };
    
        if (features && features.energy) {
            this.engine.energy = features.energy;
        }
    
        this.start = function () {
            this.engine.status = "on";
        }
    
        this.shutDown = function () {
            this.engine.status = "off";
        }
    }
    
    var car1 = new Car({
        model: "Ferrari",
        color: "red",
        energy: "100kW"
    });
    
    var car2 = new Car({
        model: "Polo",
        color: "indigo"
    });
    
    var car3 = new Car();
    
    // start all cars
    [car1, car2, car3].map(function (c) {
        c.start();
    });
    
    

    Liebe Grüße,

    Felix Riesterer.

    1. Lieber Felix,

      meine Glaskugel sagt mir, dass Du beim Schreiben der entsprechenden Code-Zeilen die völlig falsche Musik dazu gehört hast.

      du hast recht ich sollte mir doch lieber Slipknot anhören als die chart-musik ;-)

      Deswegen haben sich metaphysische Schwingungen entwickelt, die die Datenstruktur Deines Browsers durcheinander bringen

      Metaphysische schwingungen interferieren mit physischen elektrischen Datenstrom oO??? Da hab ich wohl in Physik GK gepennt xD.

      Du machst anscheinend in Deiner Konstruktor-Funktion irgend etwas mit globalen Variablen, oder Du speicherst das Ergebnis dieser mit "new" als Schlüsselwort genutzten

      Vielen lieben Dank für die Auskunft. Meld mich Morgen in diesem Threat wieder wenn ich was konkretes mit den Konstruktor angestllt habe was der mich ursache des Problems näher bringt oder lösen werde.

      Auf dann, bis bald, schönen abend, mb

      PS.: kannst du mir mal erklären was es mit nem parameter "features" und eigenschaft "features.model" auf sich hat und du die verknüpfst???

      function irgendwas (features) {
        this.model = { ...; }
        if (features && features.model) {
          ...;
        }
      }
      
      1. Hallo

        […] kannst du mir mal erklären was es mit nem parameter "features" und eigenschaft "features.model" auf sich hat und du die verknüpfst???

        Zunächst einmal hat Felix hier ein Beispiel für eine Konstruktorfunktion gegeben, welche über einige Eigenschaften und Methoden verfügt, nach dem Schema:

        var Constructor = function ( ) {
          this.property = 'value';
          this.method = function ( ) {
            return this.property;
          };
        };
        

        Nehmen wir nun an, du erzeugst eine Instanz davon, möchtest aber, dass der Wert der Eigenschaft property dieses neu erstellten Funktionsobjektes ein anderer ist, dann müsstest du hier schreiben:

        var instance = new Constructor( );
        instance.property = 'otherValue';
        

        Das ist eine Möglichkeit, aber nicht besonders elegant. Besser wäre es, der Konstruktorfunktion einen Parameter mit auf den Weg zu geben:

        var Constructor = function (val) {
          this.property = val;
          this.method = function ( ) {
            return this.property;
          };
        };
        
        var instance = new Constructor('value');
        var val = instance.method( ); // value
        

        Praktikabel wäre diese Lösung aber nicht, denn wenn wir es so schreiben und bei der Erzeugung einer Instanz kein Argument übergeben, dann wird der Parameter val und mithin die Eigenschaft property mit undefined initialisiert, und der Sinn der Übung besteht ja gerade darin, nicht jede Objekteigenschaft separat anlegen zu müssen, sondern sich Schreibarbeit zu sparen, indem man einer Stelle Eigenschaften und Methoden hinterlegt, die dann an mehrere Instanzen vererbt werden.

        Das heißt, wir wollen einerseits, dass bestimmte Defaultwerte vorhanden sind, aber andererseits wollen wir auch die Möglichkeit haben, für die jeweiligen Eigenschaften bei der Instanzierung abweichende Werte zu bestimmen. Darum müssen wir in der Konstruktorfunktion prüfen, ob ein Parameter übergeben wurde, und nur in diesem Fall wird der entsprechende Defaultwert überschrieben:

        var Constructor = function (val) {
          this.property = 'value';
          if (val) {
            this.property = val;
          }
          this.method = function ( ) {
            return this.property;
          };
        };
        
        var first = new Constructor( );
        console.log(first.method( )); // value
        
        var second = new Constructor('otherValue');
        console.log(second.method( )); // otherValue
        

        Allerdings kann man das auch etwas eleganter formulieren und statt der Prüfung mittels if-Statement folgendes schreiben:

        var Constructor = function (val) {
          this.property = val || 'value';
          this.method = function ( ) {
            return this.property;
          };
        };
        

        Nehmen wir nun aber einmal an, unsere Konstruktorfunktion hat nicht nur eine Eigenschaft, sondern zehn oder zwanzig, dann würden wir uns hier mit der Parametrisierung einen abbrechen. Daher ist es besser, statt einen Haufen einzelner Werte zu übergeben, diese Werte in einem Objekt zu hinterlegen, welches dann als einziges Argument übergeben wird:

        var Constructor = function (object) {
          this.first = 1;
          if (object && object.first) {
            this.first = object.first;
          }
          this.second = 2;
          if (object && object.second) {
            this.second = object.second;
          }
        };
        
        var param = {
          first : 'one',
          second : 'two'
        };
        
        var instance = new Constructor(param);
        console.log(instance.first); // one
        console.log(instance.second); // two
        

        Und das ist im Wesentlichen das, was Felix hier gemacht hat, mit dem Unterschied, dass er das an die Konstruktorfunktion übergebene Objekt nicht erst in einer Variable gespeichert, sondern es direkt beim Aufruf des Konstruktors erzeugt hat, also:

        var instance = new Constructor({
          first : 'one',
          second: 'two'
        });
        

        Davon abgesehen ist der Grund, weshalb hier nicht nur die Eigenschaft sondern auch auf den Parameter selbst geprüft wird, also if (object && object.property) notiert wird, der, dass falls kein Argument übergeben wurde, object mit undefined initialisiert wird, und dann würde die Prüfung der Eigenschaft hier einen type error produzieren.

        Aber auch das könnte man anders notieren:

        var Constructor = function (object) {
          this.property = object && object.property || 'value';
        };
        
        var first = new Constructor( );
        console.log(first.property); // value
        
        var second = new Constructor({ property : 'otherValue' });
        console.log(second.property); // otherValue
        

        Gruß,

        Orlok

        1. Tach!

          Darum müssen wir in der Konstruktorfunktion prüfen, ob ein Parameter übergeben wurde, und nur in diesem Fall wird der entsprechende Defaultwert überschrieben:

          Wenn du das nur so betonst, musst du den Code aber auch so schreiben, dass das nur erfüllt wird.

          var Constructor = function (val) {
            this.property = 'value';
            if (val) {
              this.property = val;
            }
          

          Angenommen this.property hätte true als Default-Wert und du möchtest ihn per Konstruktor-Parameter mit false überschreiben, dann geht das nicht, weil deine Bedingung if (val) nie wahr wird. Mit if (val !== undefined) kann man auch diesen Fall abdecken.

          Die Abkürzung mit Prüfung auf truthy- oder falsy-Werte ist legitim, man muss nur genau wissen, wann man sie einsetzen kann und wann nicht. Und diese Bedingungen dürfen sich auch nicht später ändern, wenn man vorhat, die Anpassung des Konstruktors zu vergessen.

          Nehmen wir nun aber einmal an, unsere Konstruktorfunktion hat nicht nur eine Eigenschaft, sondern zehn oder zwanzig, dann würden wir uns hier mit der Parametrisierung einen abbrechen. Daher ist es besser, statt einen Haufen einzelner Werte zu übergeben, diese Werte in einem Objekt zu hinterlegen, welches dann als einziges Argument übergeben wird:

          Und es ist auch besser, sich nicht mit 10 oder 20 Wiederholungen einen abzubrechen, sondern stattdessen über ein Array mit den erlaubten Eigenschaftennamen zu iterieren. Damit tritt auch das truthy/falsy-Problem nicht auf.

          var Constructor = function (object) {
            this.first = 1;
            this.second = 2;
          
            if (typeof object == 'object') {
              ['first', 'second'].forEach(function(name) {
                if (object.hasOwnProperty(name)) {
                  this[name] = object[name];
                }
              });
            }
          };
          

          dedlfix.

          1. var Constructor = function (val) {
              this.property = 'value';
              if (val) {
                this.property = val;
              }
            

            Angenommen this.property hätte true als Default-Wert und du möchtest ihn per Konstruktor-Parameter mit false überschreiben, dann geht das nicht, weil deine Bedingung if (val) nie wahr wird. Mit if (val !== undefined) kann man auch diesen Fall abdecken.

            EcmaScript2015 bringt eine eigene Syntax für Default-Parameter mit:

            var Constructor = function (val='value') {
               this.value = val;
            }
            

            Und es ist auch besser, sich nicht mit 10 oder 20 Wiederholungen einen abzubrechen, sondern stattdessen über ein Array mit den erlaubten Eigenschaftennamen zu iterieren. Damit tritt auch das truthy/falsy-Problem nicht auf.

            var Constructor = function (object) {
              this.first = 1;
              this.second = 2;
            
              if (typeof object == 'object') {
                ['first', 'second'].forEach(function(name) {
                  if (object.hasOwnProperty(name)) {
                    this[name] = object[name];
                  }
                });
              }
            };
            

            Ein ähnliches Ergebnis erreicht man mit Object.assign(), allerdings werden dann sämtliche Eigenschaften aus dem Parameter-Objekt übernommen, nicht nur solche, die explizit angegeben wurden.

            var Constructor = function (parameter) {
              this.first = 1;
              this.second = 2;
            
              Object.assign(this,parameter);
            };
            

            Noch eleganter finde ich es, die Default-Parameter in ein eigenes Objekt auszulagern:

            var Constructor = function (parameter) {
              const defaults = {
                 first : 1,
                 second : 2
              };
              Object.assign(this,defaults,parameter);
            };
            

            Mit Destructuring ergibt sich auch die Möglichkeit benannte Default-Parameter in der Signatur zu notieren:

            var Constructor = function ({first = 1, second = 2}) {
                Object.assign(this,arguments[0]);
            }
            

            Beim Aufruf muss dann allerdings ein Objekt übergeben werden und das funktioniert wider Kompatibilitätstabelle leider nicht mit Babel (oder ist das mein Fehler?), dafür kann man sich einen Workaround basteln:

            var Constructor = function ({first= 1, second= 2}) {
                Object.assign(this,{first,second});
            }
            

            Was auch wieder dedlfix' Lösung mit dem expliziten Listing der Parameter näher kommt. http://jsfiddle.net/pak3wddj/

            Hintergrundwissen gibt Dr. Axel Rauschmayer in seinem Blog: http://www.2ality.com/2015/01/es6-destructuring.html

          2. Hallo

            […] Angenommen this.property hätte true als Default-Wert und du möchtest ihn per Konstruktor-Parameter mit false überschreiben, dann geht das nicht, weil deine Bedingung if (val) nie wahr wird. Mit if (val !== undefined) kann man auch diesen Fall abdecken.

            Die Abkürzung mit Prüfung auf truthy- oder falsy-Werte ist legitim, man muss nur genau wissen, wann man sie einsetzen kann und wann nicht. […]

            ACK. Naja, mein Ziel war es hier, in möglichst abstrakter und vor allem einfacher Form die Frage zu beantworten, wie das Beispiel von Felix funktioniert, ohne aber dabei zuweit vom Kern der Sache abzuschweifen, das heißt, das eingebaute if-Statement stand hier stellvertretend für eine an den konkreten Einzelfall angepasste Prüfung. Aber darauf hätte ich wahrscheinlich etwas deutlicher hinweisen sollen. ;-)

            Und es ist auch besser, sich nicht mit 10 oder 20 Wiederholungen einen abzubrechen, sondern stattdessen über ein Array mit den erlaubten Eigenschaftennamen zu iterieren. Damit tritt auch das truthy/falsy-Problem nicht auf.

            Ja, aber allgemeingültig ist diese Variante genauso wenig wie meine, denn hier prüfst du ja nur, ob dem Objekt eine entsprechende Eigenschaft mitgegeben wurde, aber nicht, welchen Wert die Eigenschaft hat. Das wäre also nur dann eine Option, wenn die entsprechende Prüfung bereits an anderer Stelle vorgenommen wurde.

            Gruß,

            Orlok

            1. Tach!

              Und es ist auch besser, sich nicht mit 10 oder 20 Wiederholungen einen abzubrechen, sondern stattdessen über ein Array mit den erlaubten Eigenschaftennamen zu iterieren. Damit tritt auch das truthy/falsy-Problem nicht auf.

              Ja, aber allgemeingültig ist diese Variante genauso wenig wie meine, denn hier prüfst du ja nur, ob dem Objekt eine entsprechende Eigenschaft mitgegeben wurde, aber nicht, welchen Wert die Eigenschaft hat. Das wäre also nur dann eine Option, wenn die entsprechende Prüfung bereits an anderer Stelle vorgenommen wurde.

              Da kann ich jetzt nicht nachvollziehen, worauf du hinaus willst. Mein Konstrukt übernimmt lediglich die übergebenen Daten, bzw. von denen die mit den erlaubten Namen - mit der Prüfung, dass sie überhaupt übergeben wurden. Das macht es ohne Ansehen der Werte und mit egal welchem Wert.

              Was nicht dabei ist, ist eine fachliche Prüfung auf erlaubte Werte. Wenn man die benötigt, musst man das für die entsprechenden Parameter anders/separat lösen.

              dedlfix.

              1. Hallo

                […] Mein Konstrukt übernimmt lediglich die übergebenen Daten, bzw. von denen die mit den erlaubten Namen - mit der Prüfung, dass sie überhaupt übergeben wurden. Das macht es ohne Ansehen der Werte und mit egal welchem Wert.

                Was nicht dabei ist, ist eine fachliche Prüfung auf erlaubte Werte. Wenn man die benötigt, musst man das für die entsprechenden Parameter anders/separat lösen.

                Nichts anderes wollte ich sagen. ;-)

                Gruß,

                Orlok

        2. Hallo Orlok,

          Danke Dir. Jetzt habe ich die Methode verstanden. Danke euch beiden

          Ich selbst war fleißig und habe auch schon das konstruktor-problem gelösst. Einfach habe nich die Sichtbarkeit beachtet

          function Konstruktor(parameter) { 
           function methode() {
              ...
            }
          }
          

          statt:

          function Konstruktor(parameter) {
            this.methode = function() {
              ...
            }
          }
          

          Man kann das auch über n callback lösen aber ich habs anderweitig gelöst. Ich km ja aus der Java Ecke :-)

          schöne Grüße mb

    2. Hallo,

      meine Glaskugel sagt mir, dass Du beim Schreiben der entsprechenden Code-Zeilen die völlig falsche Musik dazu gehört hast. Deswegen haben sich metaphysische Schwingungen entwickelt, die die Datenstruktur Deines Browsers durcheinander bringen, weshalb Du nur noch das zuletzt instantiierte Objekt benutzen kannst.

      hast du deine Glaskugel beim Esoteriker erworben?

      Gruß
      Kalk

      1. Lieber Tabellenkalk,

        meine Glaskugel [...]

        hast du deine Glaskugel beim Esoteriker erworben?

        ähm, dort war sie im Sonderangebot. Woher hast Du denn Deine?

        Liebe Grüße,

        Felix Riesterer.