Browser-Kompatibilität
Kai345
- javascript
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]
Cü
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.
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
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.
Cü
Kai
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
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
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?
Cü
Kai
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
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.
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
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)
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.
Cü
Kai
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.
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?
Cü
Kai
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.
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
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
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)
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
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".