Joachim: nur array-kopie verändern

Hi,

steh grade auf dem Schlauch:

var z =  [1, 2, 3];
    var c =  z;
        c.shift()

alert(c.join())
        alert(z.join())

bei arrays erzeuge ich so immer einen Zeiger auf das Original, im Gegensatz zu Objekten. Der alert sagt also sowohl für z als auch für c "2, 3". Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

Gruesse, Joachim

--
Am Ende wird alles gut.
  1. Hi,

    Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

    soweit ich weis nicht.

    Allerdings ist das ja nicht so schwer selbst zu machen:

    Array.prototype.copy = function() {  
      return this.slice(0, this.length);  
    }
    

    (nicht getestet)

    ~Dave

    1. Hi,

      (nicht getestet)

      aber korrekt ;-)

      Gruesse, Joachim

      --
      Am Ende wird alles gut.
    2. Hallo,

      Hi,

      Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

      Jain: Man kann man mit a.slice(0) ein Array a so kopieren, dass man ein neues Array erhält. In der Kopie enthaltene Objekte sind aber trotzdem keine echten Kopien, siehe http://de.selfhtml.org/javascript/objekte/array.htm#slice@title=slice im Abschnitt "Beachten Sie".

      Gruß, Don P

  2. bei arrays erzeuge ich so immer einen Zeiger auf das Original, im Gegensatz zu Objekten.

    Ein Array ist ein Objekt. Alle Objekte werden nur referenziert.

    Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

    Nein, du musst so oder so die Inhalte kopieren. z.b. so

    Struppi.

    1. Hi,

      Nein, du musst so oder so die Inhalte kopieren. z.b. so

      blöd, das hatte ich erfolgreich verdrängt. Irgendwie nicht wirklich schön bei JS... aber letztlich ja nur etwas lästig ;-)

      Gruesse, Joachim

      --
      Am Ende wird alles gut.
    2. Hallo,

      Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

      Nein, du musst so oder so die Inhalte kopieren. z.b. so

      Das ist doch für ein Array ganz einfach: Es genügt ein slice(0) um eine perfekte Kopie zu erzeugen, die man dann beliebig manipulieren kann, ohne das Original-Array zu beeinflussen.

      Nur Änderungen an darin enthaltenen Objekten betreffen auch die Originalobjekte, aber nicht das Original-Array.

      Gruß, Don P

      1. Gibt es eigentlich keinen anderen Weg als eine Schleife, um eine "echte" Kopie zu bauen?

        Nein, du musst so oder so die Inhalte kopieren. z.b. so

        Das ist doch für ein Array ganz einfach: Es genügt ein slice(0) um eine perfekte Kopie zu erzeugen, die man dann beliebig manipulieren kann, ohne das Original-Array zu beeinflussen.

        so zeigt auf einen Thread, wo Peter S. eine Lösung mit concat zeigt, was auf selbe rauskommt. Wobei er es dort umständlich gelöst ist:

        Array.prototype.copy = function () {  
              return this.concat();  
        };  
        
        

        Nur Änderungen an darin enthaltenen Objekten betreffen auch die Originalobjekte, aber nicht das Original-Array.

        Das meinte ich mit Inhalte kopieren.

        Struppi.

        1. Hi,

          Das meinte ich mit Inhalte kopieren.

          Dennoch verstehe ich die Logik dahinter nicht ganz:

          var x = {
                  foo: "bar",
                  batz: {
                      1: 22
                  }
              }

          var y = x;
                  y = x.batz;
                  y = x.foo;

          alert(y.toSource())
              alert(x.toSource())

          jetzt bleibt mein Ausgangsobjekt so wie es ist. Setze ich jedoch beispielsweise:
              y.foo = 3;

          verändere ich mein Ausgangsobjekt. Hmm, irgendwie habe ich da ein Kapitel versäumt...

          Gruesse, Joachim

          --
          Am Ende wird alles gut.
          1. Hallo,

            Dennoch verstehe ich die Logik dahinter nicht ganz:

            [...]

            var y = x;
                    y = x.batz;
                    y = x.foo;

            alert(y.toSource())
                alert(x.toSource())

            jetzt bleibt mein Ausgangsobjekt so wie es ist.

            Klar, denn du hast ja nichts verändert am Objekt, das von x referenziert wird.
            Lediglich y hat der Reihe nach verschiedene Werte erhalten.

            Setze ich jedoch beispielsweise:
                y.foo = 3;

            verändere ich mein Ausgangsobjekt.

            Direkt nach

            var y = x;

            verweisen x und y auf genau dasselbe Ausgangsobjekt.
            Es gibt also nicht zwei davon. Wenn du dann

            y.foo = 3;

            setzt, änderst du natürlich die Eigenschaft foo des Objekts.

            So ist es auch beim Kopieren von Arrays. Nach

            var a = [x, 1, "bla"],  
                b = a.slice(0);
            

            hast du zwar verschiedene Arrays a und b, aber nicht verschiedene Objekte a[0] und b[0], sondern beide verweisen auf dasselbe Ausgangsobjekt, auf das auch x verweist. a[1] und b[1] sind aber verschiedene Variablen: Weil es keine Objekte sind, wurden sie tatsächlich kopiert, genau wie a[2] und b[2].

            Änderungen an b wirken sich nicht auf a aus, aber Änderungen am Objekt b[0] wirken sich sowohl auf a[0] als auch auf x aus, weil die ja alle identisch sind. Vielleicht ist es jetzt klarer...

            Gruß, Don P

            1. Hi,

              Änderungen an b wirken sich nicht auf a aus, aber Änderungen am Objekt b[0] wirken sich sowohl auf a[0] als auch auf x aus, weil die ja alle identisch sind. Vielleicht ist es jetzt klarer...

              Durchaus. Ich gestehe, mich zuwenig damit beschäftigt zu haben - vermutlich weil ich es noch nie gebraucht habe. Insofern ist der Thread für mich ein Augenöffner, Dank an alle...

              Gruesse, Joachim

              --
              Am Ende wird alles gut.
          2. Das meinte ich mit Inhalte kopieren.
            Dennoch verstehe ich die Logik dahinter nicht ganz:

            Das wird alles in dem von mir verlinktem Thread erklärt.

            Struppi.

            1. Hallo,

              Das wird alles in dem von mir verlinktem Thread erklärt.

              Findest du? Naja, die concat-Lösung dort gefällt mir gar nicht, und man muss für die einfache Aufgabe auch nicht unbedingt gleich am Prototyp "rumpfuschen" ;)

              Auch Objekte lassen sich übrigens kopieren (mit Einschränkungen). Crockfords geniale Funktion

              function object(o) {  
                function F() {};  
                F.prototype = o;  
                return new F();  
              }
              

              erledigt das. Man erhält ein neues Objekt mit allen Eigenschaften und Methoden des Originals im Prototyp. Wenn dann eine Eigenschaft überschrieben wird, ist das Original nicht betroffen. Dazu müsste schon die Eigenschaft des Prototyps überschrieben werden.

              Angenommen, wir wollten auf diese Weise alle Array-Inhalte wirklich kopieren, dann müsste man die Objekte gesondert behandeln, d.h. sie z.B. mit typeof untersuchen um ggf. die object-Funktion anwenden zu können, und schon sind wir wieder beim typeof null === 'object' -Problem, gell Struppi :))

              Gruß, Don P

              1. Das wird alles in dem von mir verlinktem Thread erklärt.

                Findest du? Naja, die concat-Lösung dort gefällt mir gar nicht, und man muss für die einfache Aufgabe auch nicht unbedingt gleich am Prototyp "rumpfuschen" ;)

                Mir ging es nicht um die concat Lösung - das ist doch längst gegessen - sondern darum welche Datentypen kopiert werden und welche nicht.

                Auch Objekte lassen sich übrigens kopieren (mit Einschränkungen). Crockfords geniale Funktion

                Die auch nur z.T funktionert:

                function  object(o) {  
                  function F() {};  
                  F.prototype = o;  
                  return new F();  
                }  
                  
                function A(n) {  
                	var x = n;  
                	this.a = function() {alert(x)};  
                	this.x = function(p) {x = p; };  
                }  
                var a = new A(1);  
                var b = object(a);  
                b.x(2);  
                a.a();  
                b.a();  
                
                

                Angenommen, wir wollten auf diese Weise alle Array-Inhalte wirklich kopieren, dann müsste man die Objekte gesondert behandeln, d.h. sie z.B. mit typeof untersuchen um ggf. die object-Funktion anwenden zu können, und schon sind wir wieder beim typeof null === 'object' -Problem, gell Struppi :))

                Wie gesagt, wenn du null nicht benutzen willst, darfst du es nicht benutzen. Aber als Typ muss es ein 'object' sein, sonst stimmen die Funktionen nicht mehr die immer ein Objekt als Rückgabetyp haben.

                Struppi.

                1. Hallo,

                  Mir ging es nicht um die concat Lösung - das ist doch längst gegessen - sondern darum welche Datentypen kopiert werden und welche nicht.

                  Meinetwegen.

                  Crockfords geniale Funktion

                  Die auch nur z.T funktionert:

                  function  object(o) {

                  function F() {};
                    F.prototype = o;
                    return new F();
                  }

                  function A(n) {
                  var x = n;
                  this.a = function() {alert(x)};
                  this.x = function(p) {x = p; };
                  }
                  var a = new A(1);
                  var b = object(a);
                  b.x(2);
                  a.a();
                  b.a();

                    
                  Weil b.x(2) auch das Objekt a verändert? Das meinte ich z.B. mit Einschränkungen.  
                  b kann sich natürlich keine eigene, als Closure versteckte Variable x aus dem Hut zaubern, auf die man nicht mal lesend zugreifen kann. Deshalb ist sie ja wohl auch versteckt worden, damit sie gerade nicht kopierbar ist.  
                    
                  Wenn man eine klassische Konstruktorfunktion wie A mit eingeschweißtem, unlesbarem Wert x hat, ist ein Kopieren wohl wirklich unmöglich. Wäre x wenigstens lesbar, z.B. als a.getX(), könnte man z.B. `b = new A(a.getX());`{:.language-javascript} benutzen.  
                    
                  \---  
                  
                  > Wie gesagt, wenn du null nicht benutzen willst, darfst du es nicht benutzen.  
                    
                  Es geht doch nicht darum, ob ich null benutzen WILL oder nicht, es ist nunmal da und kann an Stellen auftauchen, wo auch Objekte stehen können. typeof sagt mir aber leider den Unterschied nicht, den es tatsächlich gibt, und nur darum geht es.  
                    
                  
                  > Aber als Typ muss es ein 'object' sein, sonst stimmen die Funktionen nicht mehr die immer ein Objekt als Rückgabetyp haben.  
                    
                  Dass es intern als Object durchgeht, damit die Funktionen stimmen, ist mir doch so breit wie lang. Ich hätte nur gerne, dass typeof mich darüber nicht im Unklaren lässt. Du willst es anscheinend nicht verstehen, also lassen wir das.  
                    
                  Gruß, Don P  
                  
                  
                  1. Wie gesagt, wenn du null nicht benutzen willst, darfst du es nicht benutzen.

                    Es geht doch nicht darum, ob ich null benutzen WILL oder nicht, es ist nunmal da und kann an Stellen auftauchen, wo auch Objekte stehen können. typeof sagt mir aber leider den Unterschied nicht, den es tatsächlich gibt, und nur darum geht es.

                    Das liegt daran wofür null da ist - null ist !{object} also muss null ein object sein. Wenn du etwas anderes erwartest, darfst du halt nicht null nehmen, sondern undefined oder false.

                    Aber als Typ muss es ein 'object' sein, sonst stimmen die Funktionen nicht mehr die immer ein Objekt als Rückgabetyp haben.

                    Dass es intern als Object durchgeht, damit die Funktionen stimmen, ist mir doch so breit wie lang. Ich hätte nur gerne, dass typeof mich darüber nicht im Unklaren lässt. Du willst es anscheinend nicht verstehen, also lassen wir das.

                    Nein ich will nicht verstehen, dass du nicht einsiehst, dass es eben nur object, number, string, function, bool gibt und der einzige Typ der auf null zutrifft ist object

                    Struppi.

                    1. Hallo,

                      Wenn du etwas anderes erwartest, darfst du halt nicht null nehmen, sondern undefined oder false.

                      Ich "nehme" es doch gar nicht, sondern es wird mir z.B. von getElementById('gibtsNicht') an den Kopf geworfen.

                      Nein ich will nicht verstehen, dass du nicht einsiehst, dass es eben nur object, number, string, function, bool gibt und der einzige Typ der auf null zutrifft ist object

                      Das verstehe ich doch. Intern kann es von mir aus noch Aliens oder Dinosaurier als Typen geben; die interesieren mich alle nicht in einer weitgehend typfreien Programmiersprache. Ich verlange auch gar nicht, dass null intern ein eigener Datentyp sein soll (obwohl es so ist), sondern nur, dass mir typeof klar sagt, ob ich es mit null oder einem echten Objekt zu tun habe. Es geht um eine simple Auskunft ganz an der Oberfläche, was intern mit den Funktionen und Rückgabewerten genau passiert, ist da völlig belanglos.

                      Nochmal mit anderen Worten: Die oft zusätzlich nötige Abfrage auf null sollte einem von typeof abgenommen werden, ebenso der oft zusätzlich nötige Test, ob es sich um ein Array handelt. Das würde die internen Funktionen, Rückgabewerte usw. überhaupt nicht ankratzen, wei es sich wie gesagt nur um eine sinnvolle Auskunft für den Programmierer handelt, die ihm lästige Vergleiche erspart.

                      Gruß, Don P

                      1. Das verstehe ich doch. Intern kann es von mir aus noch Aliens oder Dinosaurier als Typen geben; die interesieren mich alle nicht in einer weitgehend typfreien Programmiersprache. Ich verlange auch gar nicht, dass null intern ein eigener Datentyp sein soll (obwohl es so ist), sondern nur, dass mir typeof klar sagt, ob ich es mit null oder einem echten Objekt zu tun habe. Es geht um eine simple Auskunft ganz an der Oberfläche, was intern mit den Funktionen und Rückgabewerten genau passiert, ist da völlig belanglos.

                        Tja, die Definition ist eine andere und letztlich willst ja doch, dass es einen zusätzlicher Typ gibt für typeof null

                        Da ich nicht weiß wie man eine Sprache entwickelt, weiß ich auch nicht weiter, wie man das begreiflich machen soll. Aber wie gesagt, ich finde es logisch, dass ein typeof null ein objekt ist, da null in meinen Pogrammen signalisiert, dass da ein Objekt erwartet wurde oder wird. Dass du typeof dazu nutzen möchtest, um mit dem Objekt zu arbeiten ist halt in dem Fall ein kollateralschaden.

                        Struppi.

                        1. Hallo,

                          Aber wie gesagt, ich finde es logisch, dass ein typeof null ein objekt ist, da null in meinen Pogrammen signalisiert, dass da ein Objekt erwartet wurde oder wird.

                          Logisch ist es, aber nicht besonders nützlich.

                          Soweit ich weiß, gibt es Datentypen u.a. deshalb, weil versch. Daten unterschiedlich viel Speicherplatz beanspruchen. Dem primitiven Wert null wäre durchaus zuzutrauen, dass er gleichviel Speicherplatz braucht wie ein veritables Objekt, und daher macht es vielleicht Sinn, ihn intern als Objekt anzusehen. Die Spezifikation sagt aber nicht, dass er ein Objekt ist, nur dass er u.a. eins repräsentieren kann.

                          Was typeof betrifft, so könnte der Operator das etwas lockerer sehen und 'null' sagen, wenn er null antrifft. Wenn mich jemand fragt, was da am Horizont auf dem Wasser schwimmt, sage ich auch "ein Schiff" und nicht "ein Fahrzeug", was zwar in gewisser Weise richtig wäre, aber eben nicht besonders hilfreich.

                          Dass du typeof dazu nutzen möchtest, um mit dem Objekt zu arbeiten ist halt in dem Fall ein kollateralschaden.

                          Kann man so sehen. Natürlich habe ich mir längst eine Krücke geklaubaut für den Fall, dass ich doch mal typeof wirklich benutzen will:

                          function typeOf(v){var s=typeof v;if(s!=='object'){return s;}if(!v){return'null';}if(typeof v.length==='number'&&!(v.propertyIsEnumerable('length'))&&typeof v.splice==='function'){return'array';}return s;};  
                          
                          

                          Hässlich, aber funktioniert.

                          (instanceof Array soll nicht ganz zuverlässig sein: Wenn ein Array z.B. in einem anderen Frame erstellt wurde, versagt instanceof es angeblich, daher die Umstände beim Erkennen von Arrays)

                          Gruß, Don P

                          1. [latex]Mae  govannen![/latex]

                            (instanceof Array soll nicht ganz zuverlässig sein: Wenn ein Array z.B. in einem anderen Frame erstellt wurde, versagt instanceof es angeblich, daher die Umstände beim Erkennen von Arrays)

                            if (Object.prototype.toString.call(v).indexOf('Array') !== -1) {  
                              return "array"  
                            }
                            

                            Cü,

                            Kai

                            --
                            Resig is more like Javascript's Pee Wee Herman.  ;) (D.Mark in clj)
                            Foren-Stylesheet Site Selfzeug JS-Lookup
                            SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
                            1. Hallo,

                              if (Object.prototype.toString.call(v).indexOf('Array') !== -1) {

                              return "array"
                              }

                                
                              Wow, eine interessante Variante. Viel schöner als meine geklaute, aber vielleicht auch langsamer, weil `toString()`{:.language-javascript} und `indexOf()`{:.language-javascript} immer ausgeführt werden müssen.  
                                
                              Meine Version ist schon nach `typeof v.length!=='number'`{:.language-javascript} fertig, wenn v kein Array ist.  
                              In Schleifen und Rekursionen kann sich das bemerkbar machen, also bleibe ich vorsichtshalber bei der hässlichen Version.  
                                
                              trotzem Danke, Don P  
                              
                              
                              1. [latex]Mae  govannen![/latex]

                                Meine Version ist schon nach typeof v.length!=='number' fertig, wenn v kein Array ist.
                                In Schleifen und Rekursionen kann sich das bemerkbar machen, also bleibe ich vorsichtshalber bei der hässlichen Version.

                                if (typeof v.length === 'number' && Object.prototype.toString.call(v).indexOf('Array') !== -1)

                                SCNR

                                Cü,

                                Kai

                                --
                                Resig is more like Javascript's Pee Wee Herman.  ;) (D.Mark in clj)
                                Foren-Stylesheet Site Selfzeug JS-Lookup
                                SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
                          2. Was typeof betrifft, so könnte der Operator das etwas lockerer sehen und 'null' sagen, wenn er null antrifft.

                            Was aber falsch wäre.

                            Eben hat Mathias das gepostet und du siehst anhand des codes den Zweck von typeof

                            if (typeof document.activeElement == "undefined" ....

                            activeElement ist entweder undefiniert oder ein object. Du möchtest noch eine dritte Möglichkeit einführen, was nur verwirrend wäre. Denn dann wäre das gegenteil nicht mehr 100% wahr.

                            if (typeof document.activeElement != "object" ....

                            Struppi.

                            1. Hallo,

                              if (typeof document.activeElement == "undefined" ....

                              activeElement ist entweder undefiniert oder ein object.

                              Es ist entweder oder definiert oder nicht. Das Gegenteil von 'undefined' ist nicht unbedingt 'object'. Man könnte activeElement auch vorher einen String zugewiesen haben oder NaN oder sowas und hätte dann ein Problem.

                              Dieselbe Unsicherheit hat man mit der üblichen Abfrage der Existenz eines Objekts:
                              if (document.activeElement) ...

                              molily hat vermutlich Anfänger als Zielgruppe und wollte sie damit nicht überfordern. Und er hätte sicher lieber auf "object" getestet als auf "undefined", was aber wegen der möglichen null bei typeof leider nicht zu empfehlen ist :(.

                              Du möchtest noch eine dritte Möglichkeit einführen, was nur verwirrend wäre. Denn dann wäre das gegenteil nicht mehr 100% wahr.

                              Verwirrend ist nur, dass man activeElement auch null zuweisen könnte und es wäre dann laut typeof noch immer ein Object, und trotzdem könnte man nicht damit arbeiten.

                              Wenn man molilys Abfrage sicherer gestalten wollte, müsste man entweder notieren:
                              if (typeof document.activeElement == "object" && document.activeElement !== null....
                              oder etwas einfacher:
                              if (document.activeElement && typeof document.activeElement == "object") ...

                              Beides wäre aber identisch mit
                              if (typeof document.activeElement == "object") ...
                              (also noch einfacher), wenn typeof null == 'null' gelten würde,
                              was zu beweisen war :P

                              Gruß, Don P

                              1. if (typeof document.activeElement == "undefined" ....

                                activeElement ist entweder undefiniert oder ein object.

                                Es ist entweder oder definiert oder nicht. Das Gegenteil von 'undefined' ist nicht unbedingt 'object'.

                                Doch natürlich ist es das, es ist ein definierte Eigenschaft, die wenn sie existiert immer ein Objekt ist.

                                molily hat vermutlich Anfänger als Zielgruppe und wollte sie damit nicht überfordern. Und er hätte sicher lieber auf "object" getestet als auf "undefined",

                                das wäre Unsinn, entweder ist typeof undefiniert, dann wird diese Eigrnschaft von dem Browser nicht unterstützt oder es ist ein Objekt, dann wird sie unterstützt.

                                Du möchtest noch eine dritte Möglichkeit einführen, was nur verwirrend wäre. Denn dann wäre das gegenteil nicht mehr 100% wahr.

                                Verwirrend ist nur, dass man activeElement auch null zuweisen könnte und es wäre dann laut typeof noch immer ein Object, und trotzdem könnte man nicht damit arbeiten.

                                Du verstehst nicht - activeElement ist immer ein Objekt! Ausser wenn es der Browser nicht unterstützt.

                                Wenn man molilys Abfrage sicherer gestalten wollte, ..

                                Das müßte man machen, wenn der Wert für activeElement nicht per Definition immer ein Objekt wäre.

                                Man muss aber in dem Fall nur prüfen ob der Wert überhaupt definiert ist. Denn er will gar nicht auf die Eigenschaft zugreifen, sondern nur feststellen, ob die Funktionalität unterstützt wird. Und das wird signalisiert dadurch, dass typeof activeElement == 'object' ist. Wenn es nach dir ginge müßte man sowohl darauf, als auch auf null prüfen. Das kann man sich aber dank der genialen Definition (Null== obbject) sparen.

                                Struppi.

                                1. Hi,

                                  if (typeof document.activeElement == "undefined" ....

                                  Du verstehst nicht - activeElement ist immer ein Objekt! Ausser wenn es der Browser nicht unterstützt.

                                  Don spielt hier mal wieder den Advocatus Diaboli, und will darauf hinaus, dass obiger Test (natürlich) nicht das gewünschte bringt, wenn man vorher selber mit bspw.
                                  document.activeElement = 4711;
                                  eine solche Eigenschaft angelegt hätte.

                                  Wobei es natürlich auch nicht viel bringen würde, wenn in folgendem ebenso konstruiertem Beispiel

                                  document.activeElement = window.location;  
                                  alert(typeof document.activeElement);
                                  

                                  dann tatsächlich "object" herauskommt, weil man daraus in der Praxis immer noch keinen sinnvollen Schluss ziehen kann, ob document.activeElement sich nun in dem Sinne verwenden lässt, der beabsichtigt ist.

                                  Man kann JavaScript praktisch im Browser anwenden, und sich dabei seine Kenntnisse über das Vorhandensein bestimmter Objekte bzw. welche Schlüsse man aus dem Nichtvorhandensein ziehen kann, zu Nutze machen - oder man kann darüber stundenlang theoretisch herumphilosophieren; und Dons Steckenpferd scheint in erster Linie letzteres zu sein :-)

                                  MfG ChrisB

                                  --
                                  “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                                  1. Hallo,

                                    Du verstehst nicht - activeElement ist immer ein Objekt! Ausser wenn es der Browser nicht unterstützt.

                                    Don spielt hier mal wieder den Advocatus Diaboli, und will darauf hinaus, dass obiger Test (natürlich) nicht das gewünschte bringt, wenn man vorher selber mit bspw.
                                    document.activeElement = 4711;
                                    eine solche Eigenschaft angelegt hätte.

                                    Genau.

                                    oder man kann darüber stundenlang theoretisch herumphilosophieren; und Dons Steckenpferd scheint in erster Linie letzteres zu sein :-)

                                    So ist es. Ich sehe: Ausnahmsweise verstehen wir uns mal :)

                                    Abgesehen vom Philosophieren halte ich das Verhalten von typeof wirklich für verbesserungswürdig (ob ihr das nun einseht oder nicht), weshalb ich auch eine Funktion typeOf() bei meinen Standardwerkzeugen habe, die besser funktioniert :P

                                    Gruß, Don P

                                    1. Abgesehen vom Philosophieren halte ich das Verhalten von typeof wirklich für verbesserungswürdig (ob ihr das nun einseht oder nicht), weshalb ich auch eine Funktion typeOf() bei meinen Standardwerkzeugen habe, die besser funktioniert :P

                                      Aber vermutlich nicht bei typeof document.activeElement === 'object'

                                      Struppi.

                                      1. Hallo,

                                        [...] weshalb ich auch eine Funktion typeOf() bei meinen Standardwerkzeugen habe, die besser funktioniert :P

                                        Aber vermutlich nicht bei typeof document.activeElement === 'object'

                                        Natürlich nicht. Wenn überhaupt, würde ich das wie üblich mit
                                        if (document.activeElement) ....
                                        abfragen. Dabei stört es nicht, dass der typeof-Operator manchmal lügt, weil man ihn gar nicht fragen muss :)

                                        Gruß, Don P

                            2. Oops, ich sehe gerade erst, dass ja auf Gleichheit mit 'undefined' getestet wurde, nicht auf Ungleichheit. Da hätte ich meine Argumentation leicht anders aufbauen müssen, aber im Prinzip stimmt sie auch so.

                              Gruß, Donp

                          3. (instanceof Array soll nicht ganz zuverlässig sein: Wenn ein Array z.B. in einem anderen Frame erstellt wurde, versagt instanceof es angeblich, daher die Umstände beim Erkennen von Arrays)

                            Mal Hand aufs Herz: Ich halte es für richtig, dass sich Autoren von Bibliotheken darüber Gedanken machen, dass Typerkennung robust funktioniert. Ich selbst habe aber noch nie den Typ eines Arrays aus einem anderen Frame prüfen wollen.

                            Selbst instanceof Array habe ich äußerst selten verwendet. In 99% der Fälle reicht Duck-Typing. Also prüfen, ob es kein Primitive ist, eine length-Eigenschaft hat und irgendwie iterierbar ist. Da es in JS ohnehin dutzende Listentypen gibt, die allesamt keine echten Arrays sind, und Bibliotheken noch unzählige hinzuerfinden, bleibt einem sowieso nichts anderes übrig.

                            Mathias

                            1. Achja: ECMAScript 5 definiert Array.isArray(), womit das Problem bald ein Ende hat. Chrome V8 implementiert die Methode auch schon, in anderen kann man sie nachrüsten.

                              Mathias

                      2. Hi,

                        Ich verlange auch gar nicht, dass null intern ein eigener Datentyp sein soll (obwohl es so ist),

                        Wieso ist es?
                        Es ist vom Typ object.

                        sondern nur, dass mir typeof klar sagt, ob ich es mit null oder einem echten Objekt zu tun habe.

                        Du hast es mit einem „echten“ Objekt zu tun, so „echt“, wie Objekte nur sein können.

                        Die oft zusätzlich nötige Abfrage auf null sollte einem von typeof abgenommen werden

                        Wo ist diese zusätzliche Abfrage denn nötig?

                        Du hast hier wiederholt getElementById als Beispiel angeführt - und gerade da kannst du dir typeof einfach sparen, if(!document.getElementById(whatever)) reicht vollkommen aus.

                        Wenn die Auskunft, dass null vom Typ object ist, nicht das ist, was du haben willst - dann verwendest du mit typeof schlicht und einfach das falsche Werkzeug.

                        MfG ChrisB

                        --
                        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                        1. Hallo,

                          Ich verlange auch gar nicht, dass null intern ein eigener Datentyp sein soll (obwohl es so ist),

                          Wieso ist es?
                          Es ist vom Typ object.

                          Weia, jetzt fängst du auch noch an... dabei hatte ich Struppi schon fast überzeugt ;)

                          Du hast es mit einem „echten“ Objekt zu tun, so „echt“, wie Objekte nur sein können.

                          Sicher nicht. Wo steht denn das? Irgendein Beweis in Sicht (außer dass typeof es uns vorgaukelt)?

                          Die oft zusätzlich nötige Abfrage auf null sollte einem von typeof abgenommen werden
                          Wo ist diese zusätzliche Abfrage denn nötig?

                          Fast überall! Z.B. immer dann, wenn mich unter versch. Daten nur die Objekte interessieren, weil ich mit ihnen etwas vorhabe, wie z.B. eine zusätzliche Eigenschaft einführen oder auch nur eine abfragen.

                          Du hast hier wiederholt getElementById als Beispiel angeführt -

                          nicht wiederholt, sondern nur einziges mal, um zu zeigen, dass man sich null nicht aussuchen muss als Rückgabewert, sondern dass sich der einfach mal ergeben kann.

                          und gerade da kannst du dir typeof einfach sparen, if(!document.getElementById(whatever)) reicht vollkommen aus.

                          Natürlich, so direkt würde ich hier auch nicht mit typeof nachfragen. Aber stell' dir eine Datenstruktur vor, die irgenwann mal befüllt wurde mit verschiedenen Funktionsergebnissen, zum Teil Objekte, auch mal null z.B. durch getElementById oder eine andere Funktion, zum Teil Zahlen, Strings, Booleans...

                          Wenn die Auskunft, dass null vom Typ object ist, nicht das ist, was du haben willst - dann verwendest du mit typeof schlicht und einfach das falsche Werkzeug.

                          Kennst du denn ein geeigneteres Werkzeug, um z.B. gezielt die Objekte in besagter Datenstruktur anzusprechen um ihnen z.B. eine neue Eigenschaft zu geben? typeof ist für solche Aufgaben schon geeignet (und ich glaube auch dafür erfunden worden), aber dummerweise nur mit zusätzlichen Abfragen.

                          Mal anders gefragt:
                          Was würde man verlieren, wenn typeof null als Ergebnis 'null' lieferte und typeof [] als Ergebnis 'array'?
                          Richtig: Gar nichts würde man verlieren außer dem Nachteil, solches ggf. umständlich durch zusätzlichen Code in Erfahrung bringen zu müssen, was also de facto ein Vorteil wäre.

                          Gruß, Don P

                          1. Hi,

                            Du hast es mit einem „echten“ Objekt zu tun, so „echt“, wie Objekte nur sein können.

                            Sicher nicht. Wo steht denn das? Irgendein Beweis in Sicht (außer dass typeof es uns vorgaukelt)?

                            typeof gaukelt dir nichts vor, sondern es ist *definiertes* Verhalten, dass typeof null „object” liefert.

                            http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf, 11.4.3 The typeof Operator

                            Ich verstehe echt nicht, warum du derart oft den Bedarf siehst, definiertes Verhalten in der Art und Weise zu diskutieren, in der du es oftmals tust.

                            Aber stell' dir eine Datenstruktur vor, die irgenwann mal befüllt wurde mit verschiedenen Funktionsergebnissen, zum Teil Objekte, auch mal null z.B. durch getElementById oder eine andere Funktion, zum Teil Zahlen, Strings, Booleans...

                            Vielleicht sind solche „Datenstrukturen“ dein eigentliches Problem?
                            Ich sehe selten die Notwendigkeit, typeof überhaupt zu verwenden.

                            Wenn du natürlich erst mal alles auf einen großen Haufen schmeißt, dann ist es nachvollziehbar, dass du diesen Klumpatsch auch mühsam wieder auseinanderklamüsern musst. Der Versuch, eierlegende Wollmilchsäue zu programmieren, hat natürlich auch seine Nachteile.

                            Kennst du denn ein geeigneteres Werkzeug, um z.B. gezielt die Objekte in besagter Datenstruktur anzusprechen um ihnen z.B. eine neue Eigenschaft zu geben?

                            Meine Datenstrukturen baue ich möglichst so auf, dass ich schon weiss, was ich wo rein gepackt habe - dann muss ich nicht erst beim Herausfischen alles drei mal hin- und herdrehen und überlegen, „was hab ich hier eigentlich gerade in der Hand ...?“

                            Was würde man verlieren, wenn typeof null als Ergebnis 'null' lieferte und typeof [] als Ergebnis 'array'?
                            Richtig: Gar nichts würde man verlieren außer dem Nachteil, solches ggf. umständlich durch zusätzlichen Code in Erfahrung bringen zu müssen, was also de facto ein Vorteil wäre.

                            Alles gut und schön - aber leider hast du zu spät angefangen, Einfluss auf die ECMAScript-Spezifikation zu nehmen, und jetzt ist sie nun mal so, wie sie ist.

                            MfG ChrisB

                            --
                            “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                            1. Hallo,

                              typeof gaukelt dir nichts vor, sondern es ist *definiertes* Verhalten, dass typeof null „object” liefert.

                              http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf, 11.4.3 The typeof Operator

                              Du hast dich zu spät eingeschaltet; das hatten wir alles schon (dieses ist schon der zweite Tread dazu). Es ist _leider_ so definiert, könnte besser sein. Jetzt ist es natürlich zu spät, etwas daran zu ändern. Aber diskutieren, ob die Spezifikation hier Sinn macht, darf man doch. Einfach so.

                              Ich verstehe echt nicht, warum du derart oft den Bedarf siehst, definiertes Verhalten in der Art und Weise zu diskutieren, in der du es oftmals tust.

                              Ich mag eben Gundsatzdiskussionen, und Strupppi anscheinend dauch. Das ist alles. Oft kommen interesante Erkenntnisse dabei heraus, auf die man sonst nie gekommen wäre. Ich denke, wir haben unseren Spass dabei :)

                              Vielleicht sind solche „Datenstrukturen“ dein eigentliches Problem?
                              Ich sehe selten die Notwendigkeit, typeof überhaupt zu verwenden.

                              Hatten wir auch schon: Ich benutze es auch so gut wie nie.

                              Meine Datenstrukturen baue ich möglichst so auf, dass ich schon weiss, was ich wo rein gepackt habe - dann muss ich nicht erst beim Herausfischen alles drei mal hin- und herdrehen und überlegen, „was hab ich hier eigentlich gerade in der Hand ...?“

                              Ordnung ist das halbe Leben... Wenn man oo programmiert, hat man schon manchmal das Bedürfnis, bequem über alle Objekteigenschaften zu iterieren, und die können auch verschiedenen Typs sein. Oder sind alle deine Objekte nach Datentypen sortiert? Die nativen DOM-Objekte sind es z.B. nicht.

                              Gruß, Don P

                        2. [latex]Mae  govannen![/latex]

                          Du hast hier wiederholt getElementById als Beispiel angeführt - und gerade da kannst du dir typeof einfach sparen, if(!document.getElementById(whatever)) reicht vollkommen aus.

                          Ja.

                          Und selbst wenn man es — aus welchen Gründen auch immer — „ausführlicher“ schreiben wollen würde, wäre hier
                          if (document.getElementById(whatever) === null) immer noch ausreichend, da gEBI entweder eine Elementreferenz oder null zurückgibt. Den typeof-Operator braucht man hier nicht.

                          Cü,

                          Kai

                          --
                          Resig is more like Javascript's Pee Wee Herman.  ;) (D.Mark in clj)
                          Foren-Stylesheet Site Selfzeug JS-Lookup
                          SelfCode: sh:( fo:| ch:? rl:( br:< n4:( ie:{ mo:| va:) js:| de:> zu:) fl:( ss:| ls:?
                  2. Crockfords geniale Funktion

                    Die auch nur z.T funktionert:

                    function  object(o) {

                    function F() {};
                      F.prototype = o;
                      return new F();
                    }

                    function A(n) {
                    var x = n;
                    this.a = function() {alert(x)};
                    this.x = function(p) {x = p; };
                    }
                    var a = new A(1);
                    var b = object(a);
                    b.x(2);
                    a.a();
                    b.a();

                    
                    >   
                    > Weil b.x(2) auch das Objekt a verändert? Das meinte ich z.B. mit Einschränkungen.  
                    > b kann sich natürlich keine eigene, als Closure versteckte Variable x aus dem Hut zaubern, auf die man nicht mal lesend zugreifen kann. Deshalb ist sie ja wohl auch versteckt worden, damit sie gerade nicht kopierbar ist.  
                      
                    Ja aber nur für das eine Objekt.  
                      
                    
                    > Wenn man eine klassische Konstruktorfunktion wie A mit eingeschweißtem, unlesbarem Wert x hat, ist ein Kopieren wohl wirklich unmöglich.  
                      
                    Nicht wirklich:  
                    ~~~javascript
                    Object.prototype.copy = function() {  
                    	return new this.constructor();  
                    }  
                    function A(n) {  
                            var x = n;  
                            this.a = function() {alert(x)};  
                            this.x = function(p) {x = p; };  
                    }  
                    var a = new A(1);  
                    var b = a.copy();  
                    b.x(2);  
                    a.a();  
                    b.a();  
                    
                    

                    Struppi.

                    1. Hallo,

                      Wenn man eine klassische Konstruktorfunktion wie A mit eingeschweißtem, unlesbarem Wert x hat, ist ein Kopieren wohl wirklich unmöglich.

                      Nicht wirklich

                      Doch, denn deine copy-Funktion kopiert nicht das Objekt a, sondern erzeugt nur ein jungfräulich neues:

                      Object.prototype.copy = function() {  
                      	return new this.constructor();  
                      }  
                      function A(n) {  
                              var x = n;  
                              this.a = function() {alert(x)};  
                              this.x = function(p) {x = p; };  
                      }  
                      var a = new A(1);  
                      var b = a.copy();  
                      //b.x(2);  
                      a.a(); // 1  
                      b.a(); // undefined !!!
                      

                      Dafür hätte ein einfaches var b = new A(); gereicht.
                      Die object-Funktion dagegen erhält wenigstens das x, aber halt nicht als eigenes, und man kann es auch durch nachträgliche Zuweisung nicht hinbekommen.

                      => Wirklich kopieren geht wohl doch nicht in so einem Fall.

                      Gruß, Don P