Kai345: Browser-Kompatibilität

Grütze .. äh ... Grüße!

So, nachdem ich mir beim Schreiben des  Betreffs fast die Finger verknotet habe (schreibt das Wort mal selber .. brrr), nun mein Anliegen:

Ich bin gerade dabei, mein Javasript abwärtstauglich zu machen, denn
im IE5.01 [1] hat es mir das Script "gerissen", weil z.B. splice() erst ab IE5.5 existiert.

Durch Abfrage der Existenz einer Methode oder Eigenschaft vor dem Aufruf  kann ich bekanntlich verhindern, daß so ein Fehler auftritt.

Aber wie frage ich nun am Besten ab?

wenn ich schreibe

var abc = [1,2,3,4];  
alert(abc.splice);

dann erhalte ich je nach Browser erwartungsgemäß entweder eine Funktion oder "undefined" und kann mit

if (abc.splice) {  
  // allerlei  
}

entsprechend abfragen.

Nun ist es so, daß ich eine ganze Funktion nur ausführen will, wenn die Methode splice existiert, das Array wird aber erst innerhalb der Funktion erzeugt. Ich könnte zwar tricksen und ein dummy-Array benutzen:

alert([].splice);

aber das finde ich programmiertechnisch ziemlich unschön.

Gibt es noch eine andere, evtl. generische Methode oder müßte ich es wie oben schreiben? Array.splice scheint nicht zu funktionieren. Und wie sieht es mit Methoden anderer Objekte aus? [2]


Kai

[1] Da das Ganze größtenteils auch eine Lernübung ist, berücksichtige ich auch solche Browser noch ;)

[2] Sorry fürs dumme Fragen, aber bin eben noch lange kein Experte.

--
What is the difference between Scientology and Microsoft? One is an
evil cult bent on world domination and the other was begun by L. Ron
Hubbard.
ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
  1. Yerf!

    Gibt es noch eine andere, evtl. generische Methode oder müßte ich es wie oben schreiben? Array.splice scheint nicht zu funktionieren. Und wie sieht es mit Methoden anderer Objekte aus? [2]

    Array.splice funktioniert bei mir im FF für diese Zweck, aber nicht im IE.

    Ein javascript:alert(Array.prototype.splice); zeigt auch im IE(6) das gewünschte Ergebnis.

    Gruß,

    Harlequin

    --
    <!--[if IE]>This page is best viewed with a webbrowser. Get one today!<![endif]-->
    1. Grütze .. äh ... Grüße!

      Array.splice funktioniert bei mir im FF für diese Zweck, aber nicht im IE.

      In Opera übrigens auch nicht

      Ein javascript:alert(Array.prototype.splice); zeigt auch im IE(6) das gewünschte Ergebnis.

      Ebenso im IE5.5, FF1.5, Safari/Win, Seeaffe(g), Maxthon2 und Opera9.

      Super.


      Kai

      --
      What is the difference between Scientology and Microsoft? One is an
      evil cult bent on world domination and the other was begun by L. Ron
      Hubbard.
      ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
      1. gruss Kai,

        Array.splice funktioniert bei mir im FF für diese Zweck, aber nicht im IE.

        In Opera übrigens auch nicht

        im ersten fall hat es der mozilla.org gefallen, die array-methode [splice]
        generisch zur verfuegung zu stellen. warum weis ich nicht, denn als erstes
        argument werden wiederum nur arrays und eben nicht alle moeglichen listen-
        aehnlichen strukturen akzeptiert. der rest verhaelt sich entsprechend der
        offiziell gueltigen spezifikation.

        Ein javascript:alert(Array.prototype.splice); zeigt auch im IE(6) das gewünschte Ergebnis.

        Ebenso im IE5.5, FF1.5, Safari/Win, Seeaffe(g), Maxthon2 und Opera9.

        Super.

        wie auch nicht anders zu erwarten, da [splice], sofern es denn implementiert
        wurde, ueber den [prototype]n des [[Array]]-konstruktors an array-objekte
        *vererbt* werden sollte, um dem sprachkonzept gerecht zu werden.

        eine pruefung, die auf allen ECMAScript-konformen (nach ECMA 262) clients
        laeuft, saehe dann auch so aus:

        if (typeof Array.prototype.splice != "function") { /*...*/ }

        ansonsten kannst Du es aber durchaus mit Cheatahs vorschlag halten.

        so long - peterS. - pseliger@gmx.net

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
  2. Hi,

    alert([].splice);
    aber das finde ich programmiertechnisch ziemlich unschön.

    warum? Es trifft - leicht erkennbar - den Kern der Sache. _Und_ es funktioniert. Was willst Du mehr? :-)

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Grütze .. äh ... Grüße!

      alert([].splice);
      aber das finde ich programmiertechnisch ziemlich unschön.

      warum? Es trifft - leicht erkennbar - den Kern der Sache. _Und_ es funktioniert. Was willst Du mehr? :-)

      Klar funktioniert es so, aber wird dadurch nicht ein zusätzliches Array angelegt?


      Kai

      --
      What is the difference between Scientology and Microsoft? One is an
      evil cult bent on world domination and the other was begun by L. Ron
      Hubbard.
      ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
      1. Hi,

        Klar funktioniert es so, aber wird dadurch nicht ein zusätzliches Array angelegt?

        ja. Diesen Performance-Verlust halte ich aber für vertretbar.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
  3. Nun ist es so, daß ich eine ganze Funktion nur ausführen will, wenn die Methode splice existiert, das Array wird aber erst innerhalb der Funktion erzeugt. Ich könnte zwar tricksen und ein dummy-Array benutzen:

    alert([].splice);

    aber das finde ich programmiertechnisch ziemlich unschön.

    Gibt es noch eine andere, evtl. generische Methode oder müßte ich es wie oben schreiben? Array.splice scheint nicht zu funktionieren. Und wie sieht es mit Methoden anderer Objekte aus? [2]

    Selbst die Funktion schreiben, wie das geht siehst du z.b. hier http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach

    if (!Array.prototype.forEach)  
    {  
      Array.prototype.forEach = function(fun /*, thisp*/)  
      {  
        var len = this.length;  
        if (typeof fun != "function")  
          throw new TypeError();  
      
        var thisp = arguments[1];  
        for (var i = 0; i < len; i++)  
        {  
          if (i in this)  
            fun.call(thisp, this[i], i, this);  
        }  
      };  
    }  
    
    

    Das kannst du genauso mit splice machen.

    Struppi.

    1. Moin Moin!

      Selbst die Funktion schreiben

      Oder jemanden finden, der sowas mal eben aus dem CVS-Repository kramt und hiermit ohne Garantie und unter Ausschluß jeglicher Gewährleistungsansprüche der Öffentlichkeit spendet.

      Nur bleibt's nicht beim splice, weil antike IEs auch einige andere Array-Methoden nicht kennen. Die sind aber relativ trivial zu implementieren.

        
      if (null==Array.prototype.push) {  
       Array.prototype.push=function()  
       {  
        for (var i=0; i<arguments.length; i++) this[this.length]=arguments[i];  
        return this.length; // Verhalten von JS > 1.2  
       };  
      }  
      if (null==Array.prototype.pop) {  
       Array.prototype.pop=function()  
       {  
        return this[this.length--];  
       };  
      }  
      if (null==Array.prototype.shift) {  
       Array.prototype.shift=function()  
       { // schnell implementiert, aber nicht schnell ;-)  
        this.reverse();  
        var rv=this.pop();  
        this.reverse();  
        return rv;  
       };  
      }  
      if (null==Array.prototype.unshift) {  
       Array.prototype.unshift=function()  
       { // schnell implementiert, aber nicht schnell ;-)  
        this.reverse();  
        for (var i=arguments.length-1; i>=0; i--) this[this.length]=arguments[i];  
        this.reverse();  
        return this.length;  
       };  
      }  
      if (null==Array.prototype.splice) {  
       Array.prototype.splice=function(start,count)  
       {  
        var removed=new Array();  
        var tail=new Array();  
        var i;  
        if (start<0) start+=this.length;  
        for (i=0; i<count; i++) removed.push(this[start+i]);  
        for (i=start+count; i<this.length; i++) tail.push(this[i]);  
        this.length=start;  
        for (i=2; i<arguments.length; i++) this[this.length]=arguments[i];  
        for (i=0; i<tail.length; i++) this.push(tail[i]);  
        return removed;  
       };  
      }  
      
      

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      1. gruss Alexander,

        »»~~~Javascript if (null==Array.prototype.push) { /* code */ }
        // ----^^^^^^

          
        niemals nicht! das funktioniert nur, weil du die primitiven werte  
        der typen [Null] und [Undefined] einem vergleich unterziehst, der  
        nicht typsicher und damit unscharf ist, da typwandlung zugelassen  
        wird.  
          
        durch den vergleichsoperator »==« schluepfen ausserdem noch die  
        werte [""], [0], [false]. vergleiche dieser art validieren in  
        allen faellen zu [true], sobald die drei letztgenannten werte  
        untereinander verglichen werden - und eben auch (null == undefined).  
          
        dieses verhalten kann gewuenscht sein, meistens ist es aber eine  
        fehlerquelle. fuer typsicheres vergleichen bediene man sich des  
        opeartors »===«.  
          
        wenn Du den wert [undefined] erfragen moechtest, mache gebrauch  
        vom dafuer vorgesehenen operator »typeof«.  
          
          
          
        so long - peterS. - pseliger@gmx.net  
          
          
        
        -- 
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.  
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - [Douglas Crockford](http://javascript.crockford.com/)  
          
        [ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:\]](http://www.peter.in-berlin.de/projekte/selfcode/?code=ie%3A%28+fl%3A%29+br%3A%3E+va%3A%28+ls%3A%26+fo%3A%29+rl%3A%29+n3%3B%7D+n4%3A%7D+ss%3A%7D+de%3A%B5+js%3A%7D+mo%3A%3F+zu%3A%5D)
        
        1. Grütze .. äh ... Grüße!

          »»~~~Javascript

          if (null==Array.prototype.push) { /* code */ }

          // ----^^^^^^

          
          >   
          > niemals nicht! das funktioniert nur, weil du die primitiven werte  
          > der typen [Null] und [Undefined] einem vergleich unterziehst, der  
          > nicht typsicher und damit unscharf ist, da typwandlung zugelassen  
          > wird.  
            
          Wie abfragesicher ist eigentlich in diesem speziellen Fall (d.h. Abfrage, ob Methode / Eigenschaft verfügbar) die negierte Abfrage, z.B.  
            
          ~~~javascript
          if (!Array.prototype.push) {  
            // code  
          }
          

          Generell wäre if (!wert) {//hurz!} ja ziemlich unscharf, weil der if-block ausgeführt wird, sobald "wert" irgendwas außer {null, false, 0,"" , undefined} ist.


          Kai

          --
          What is the difference between Scientology and Microsoft? One is an
          evil cult bent on world domination and the other was begun by L. Ron
          Hubbard.
          ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
          1. Generell wäre if (!wert) {//hurz!} ja ziemlich unscharf, weil der if-block ausgeführt wird, sobald "wert" irgendwas außer {null, false, 0,"" , undefined} ist.

            Ist doch ok, wenn du als falschen Wert einen von diesen erwartest dürftest du mit ! ausreichend bedient sein.

            Struppi.

            1. Grütze .. äh ... Grüße!

              Generell wäre if (!wert) {//hurz!} ja ziemlich unscharf, weil der if-block ausgeführt wird, sobald "wert" irgendwas außer {null, false, 0,"" , undefined} ist.

              Ist doch ok, wenn du als falschen Wert einen von diesen erwartest dürftest du mit ! ausreichend bedient sein.

              Das ist ja gerade die Frage, die mich beschäftigt. Ist es z.B. bei allen Browsern und immer sichergestellt [also als spezifizierter MUSS-Rückgabewert], daß einer dieser Werte zurückgegeben wird? Was ist z.B. bei einem potentiell möglichen Browserbug, der z.B. als Rückgabewert auf einmal 42 zurückgibt?

              Also besser immer auf if (Methode === "undefined") testen?


              Kai

              --
              What is the difference between Scientology and Microsoft? One is an
              evil cult bent on world domination and the other was begun by L. Ron
              Hubbard.
              ie:{ fl:( br:< va:) ls:? fo:| rl:? n4:° ss:{ de:] js:| ch:? mo:| zu:|
              1. Ist doch ok, wenn du als falschen Wert einen von diesen erwartest dürftest du mit ! ausreichend bedient sein.

                Das ist ja gerade die Frage, die mich beschäftigt. Ist es z.B. bei allen Browsern und immer sichergestellt [also als spezifizierter MUSS-Rückgabewert], daß einer dieser Werte zurückgegeben wird?

                Ja.

                Also besser immer auf if (Methode === "undefined") testen?

                Nein, nur wenn dir daran gelegen ist das es wirklich 100% das gleiche ist.

                Struppi.

          2. Hallo,

            Wie abfragesicher ist eigentlich in diesem speziellen Fall (d.h. Abfrage, ob Methode / Eigenschaft verfügbar) die negierte Abfrage, z.B.

            if (!Array.prototype.push) {

            // code
            }

            
            >   
            > Generell wäre `if (!wert) {//hurz!}`{:.language-javascript}  
            > ja ziemlich unscharf, weil der if-block ausgeführt wird, sobald "wert" irgendwas außer {`null, false, 0,"" , undefined`{:.language-javascript}} ist.  
              
            Das ist ja genau die Absicht. Denn wenn Array.prototype.push irgendwie nicht "falsy" (d.h. nicht zu false evaluiert), dann gibt es eine Eigenschaft oder Methode namens Array.prototype.push, und natürlich sollte man erwarten, dass das die bekannte push-Funktion ist.  
              
            Wenn nicht, hat ein Dilettant vorher Array.prototype um push erweitert, ohne zu wissen, dass das Ding normalerweise eine ganz bestimmte Funktion erfüllt.  
              
            Gruß, Don P
            
            1. gruss Don P,

              Das ist ja genau die Absicht. Denn wenn Array.prototype.push irgendwie nicht
              "falsy" (d.h. nicht zu false evaluiert), dann gibt es eine Eigenschaft oder
              Methode namens Array.prototype.push, und natürlich sollte man erwarten, dass
              das die bekannte push-Funktion ist.

              nun unterlauf mal nicht meine bemuehungen, den leuten einen besseren stil durch
              defensive programmieransaetze beizubringen ;-)

              siehe auch ...In diesem Fall ist es erwünscht, ...

              Wenn nicht, hat ein Dilettant vorher Array.prototype um push erweitert, ohne
              zu wissen, dass das Ding normalerweise eine ganz bestimmte Funktion erfüllt.

              jo.

              so long - peterS. - pseliger@gmx.net

              --
              »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
              Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
              ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
          3. hallo again Kai,

            Wie abfragesicher ist eigentlich in diesem speziellen Fall
            (d.h. Abfrage, ob Methode / Eigenschaft verfügbar) die
            negierte Abfrage, z.B.

            if (!Array.prototype.push) {

            // code
            }

              
            da in diesem speziellen fall eine methode nachgefragt werden  
            soll, ist jede pruefung, die nicht auf eine existierende  
            funktion besteht, unsicher.  
            zwar identifizieren sich im internet explorer einige methoden  
            des DOM als objekte, fuer den sprachkern, wie in dem von Dir  
            nachgefragten beispiel, ist dies aber irrelevant.  
              
            
            > Generell wäre `if (!wert) {//hurz!}`{:.language-javascript} ja ziemlich unscharf,  
            > weil der if-block ausgeführt wird, sobald "wert" irgendwas außer {~~~javascript
            
            null, false, 0, "",  
            
            > undefined
            
            ~~~} ist.  
              
            genau.  
              
              
              
            so long - peterS. - pseliger@gmx.net
            
            -- 
            »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.  
            Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - [Douglas Crockford](http://javascript.crockford.com/)  
              
            [ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:\]](http://www.peter.in-berlin.de/projekte/selfcode/?code=ie%3A%28+fl%3A%29+br%3A%3E+va%3A%28+ls%3A%26+fo%3A%29+rl%3A%29+n3%3B%7D+n4%3A%7D+ss%3A%7D+de%3A%B5+js%3A%7D+mo%3A%3F+zu%3A%5D)
            
        2. Hallo,

          »»~~~Javascript

          if (null==Array.prototype.push) { /* code */ }

          // ----^^^^^^

          
          >   
          > niemals nicht! [...]  
          > dieses verhalten kann gewuenscht sein, meistens ist es aber eine  
          > fehlerquelle.  
            
          In diesem Fall ist es erwünscht, deshalb sollte man einfach nur schreiben:  
            
          ` if (Array.prototype.push) { //... }`{:.language-Javascript}  
            
          Gruß, Don P
          
        3. Moin Moin!

          »»~~~Javascript

          if (null==Array.prototype.push) { /* code */ }

          // ----^^^^^^

          
          >   
          > niemals nicht! das funktioniert nur, weil ...  
            
          Stimmt schon, der ganze Block mit der IE-Array-Aufrüstung auf JS 1.3 ist irgendwann komplett aus der Entwicklung rausgefallen, weil die Minimalvoraussetzungen mal fröhlich auf IE 5.5 oder neuer geändert wurden. Bis dahin war das nur ein schneller Hack, teilweise aus einem noch älteren Projekt herauskopiert, um einen vorzeigbaren, lauffähigen Zustand zu haben.  
            
          Aber wie heißt es so schön: Einem geschenkten Barsch schaut man nicht hinter die Kiemen. ;-)  
            
          Alexander
          
          -- 
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".