Unterschied zwischen null, false und 0
Raik
- javascript
Hallo!
Ich habe beim Ausprobieren des Feature-Artikels "Auf Dateien mit JavaScript zugreifen" von Daniel Thoma Probleme mit dem Rückgabewert "null" des Applets gehabt.
http://aktuell.de.selfhtml.org/artikel/javascript/file-open/index.htm
Das zeilenweise Auslesen mit dem empfohlenen "while ((line = document.fileopener.readFile()) != null)" führte zu einem Fehler des Applets.
Nachdem ich es so probiert habe: "while (line = document.fileopener.readFile())", ging es.
Ebenfalls so: "var ende = new Boolean(false); while ((line = document.fileopener.readFile()) != ende)" .
Das brachte mich zu folgendem Versuch:
<script type=text/javascript>
d1= new Boolean(null);
d2= new Boolean(false);
d3= new Boolean(0);
d4= new Boolean();
if(d1==null){document.write('d1<br>')}
if(d2==false){document.write('d2<br>')}
if(d3==0){document.write('d3<br>')}
if(d4==0){document.write('d4==0<br>')}
if(d4==false){document.write('d4==false<br>')}
if(d4==null){document.write('d4==null<br>')}
if(d1==d2){document.write('d1==d2<br>')}
if(d2==d3){document.write('d2==d3<br>')}
if(d3==d4){document.write('d3==d4<br>')}
</script>
Im IE6 gibt es als Ergebnis:
d2
d3
d4==0
d4==false
Mich würden die Ergebnisse anderer Browser interessieren.
Wäre nett, wenn ihr die hier mit reinpostet.
freundl. Grüsse aus Berlin, Raik
Mich würden die Ergebnisse anderer Browser interessieren. Wäre nett, wenn ihr die hier mit reinpostet.
es gibt ganz viele browser, die kann man sich runterladen und installieren zum testen: http://www.mozilla.org (mozilla 1.6, und firefox 0.8) http://www.netscape.com http://www.opera.com http://lynx.browser.org/ (der beste und schnellste ;-))
aber ich will ja nicht so sein: mein firefox gibt folgendes aus d2 d3 d4==0 d4==false
(schätze mal das wird mozilla, sowie netscape auch tun)
gruss Raik,
...
Das brachte mich zu folgendem Versuch:
...
javascript ist nur lose typisiert;
jeder js-interpreter wertet den typ eines datums auch abhaengig
von dessen umgebung aus;
Dein beispiel nimmt sich den konstruktor Boolean vor, "gefuettert"
wird er mit argumenten jeweils unterschiedlichen typs;
boolean-objekte koennen aber nur die werte false bzw. true
einnehmen - der konstruktor bewertet die argumente dahingehend;
ohne argument oder mit einem undefinierten argument wird der
konstruktor immer den wert false liefern, aber auch die argumente
0, null und "" werden dahingehend ausgewertet - schon der einsatz
jeden anderen wertes, und sei es z.b. "0" liefert ein boolean-objekt
mit dem wert true zurueck;
fuer Dein gegebenes beispiel bedeutet dies, dass Deine variablen
d1, d2, d3 bzw. d4 boolean-objekte jeweils mit dem wert false sind -
Du trittst also bei deren spaeteren einsatz immer mit deren false-
werten an, die Du dann auf die werte null, false und 0 vergleichst:
d1: (false == null) // false;
d2: (false == false) // true;
d3: (false == 0) // true;
d4: (false == 0) // true; (das hatten wir grade)
d4: (false == false) // true; (kurz davor dies auch)
d4: (false == null) // false;( ... siehe oben ... )
a) ein null-wert bleibt auch im kontext eines boolean-wertes null;
b) boolean-werte koennen problemlos miteinander verglichen werden;
c) der wert 0 vom typ number konvertiert im kontext eines boolean-wertes zu false;
d) der wert "" vom typ string konvertiert im kontext eines boolean-wertes zu false;
nach dieser ausfuehrung mag es verwirren, warum fuer
den auf den ersten blick eindeutigen fall von:
d1:false, d2:false, d3:false, d4:false
nun nicht (d1==d2==d3==d4) gleich true gelten soll,
obwohl (false==false) gleich true ja offensichtlich gilt.
an dieser stelle stolperst Du ueber das problem, objekte aber nicht
deren werte miteinander zu vergleichen, denn Du hast den Boolean-
konstruktor einem einfachen boolean-literal vorgezogen - der beweis:
var d5=false, d6=false, d7=new Boolean(), d8=new Boolean();
alert(typeof(d5)) // boolean;
alert(typeof(d6)) // boolean;
alert(typeof(d7)) // object;
alert(typeof(d8)) // object;
alert(d5 == d6) // true;
alert(d5 == d8) // true;
alert(d6 == d7) // true;
//ABER:
alert(d7 == d8) // false;
Du kannst d5 und d6 untereinander, beide aber auch mit d7 bzw. d8
vergleichen, da die werte d5 und d6 beim vergleich mit den objekten
d7 und d8 den kontext fuer eine typenkonvertierung bieten - objekte
hingegen lassen sich weder mit dem gleichheits[==] - noch mit dem
identitaets[===]-operator vergleichen, dazu beduerfte es der noch
zu schreibenden prototypen methode "Object.equals";
in diesem fall kann man aber auch abhilfe schaffen, indem man die
fuer objekte eingebaute methode "toString" auf die boolean-objekte
wie folgt anwendet:
alert(d7.toString());
alert(d8.toString());
alert(d7.toString()==d8.toString());
fazit:
* das von Dir beschriebene verhalten ist ein grundsaetzliches;
* jetzt ist es vielleicht verstaendlicher, warum ich in meinen
ausfuehrungen so auf typ, wert und objekt herumgeritten bin;
regeln:
* die "primitiven" typen boolean, number und string kommen als
solche nur ueber ihre literalschreibweise zur anwendung:
var bool = true;
var num = 123;
var str = "hi";
* konstruktoren erzeugen objekte, denen werte zugewiesen sind:
new Boolean(), new String() und new Number() sind nicht
"primitiv" im sinne der ersten regel (und eigentlich gibt es
diese terminologie in javascript auch ueberhaupt nicht [aber
trotzdem wird der typeof-operator sehr oft bemueht]);
* besondere aufmerksamkeit sollte man den einfachen vergleichen
[==] auf 0, null und "" widmen - typenkonvertierung verhindert
hier nur der identitaetsoperator[===]; im gleichen zusammenhang
ist auch darauf zu achten, dass jegliche pruefung auf die existenz
von objekten fehlschlaegt "if (myObject) {...}", wenn diese einen
der obigen werte haben; der "if"-block wird nie abgearbeitet,
obschon es ein definiertes "myObject" gibt;
* gute type-detection ist die grundlage fuer eine schnelle und
fehlerfreie entwicklung in schwach typisierten sprachen wie
javascript:
http://www.pseliger.de/jsExtendedApi/jsApi.Object.typeDetection.dev.js
http://www.pseliger.de/jsExtendedApi/jsApi.Object.typeDetection.js
credits:
* vor einem jahr las ich http://www.crockford.com/javascript/remedial.html,
sodass Douglas Crockford in dieser hinsicht als mein lehrmeister betrachtet
werden kann;
gute nacht fuer mich - guten morgen fuer Euch - peterS. - pseliger@gmx.net
Hallo, peter!
Vielen Dank für diese hochinteressanten, lehrreichen Ausführungen! :-)
Dann hätte ich noch eine frage an die Java-experten:
die ursprüngliche Schreibweise:
public void setFile(String file)
{
/* file wird verwendet ... */
}
Da das beim Einbau des Security-Managers einen Fehler gibt (file muss final sein), hab ich es so gelöst:
public String uri;
public String returnUri()
{
return uri;
}
public void setFile(String file)
{
uri = file;
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
String filea = returnUri();
/* filea wird verwendet ... */
return null;
}
});
}
Ist meine Lösung zu umständlich oder gar falsch ?
Wie würde das ein Profi lösen?
freundl. Grüsse aus Berlin, Raik
Hi,
alert(typeof(d5)) // boolean;
identitaets[===]-operator vergleichen, dazu beduerfte es der
Der Vollständigkeit sei nach erwähnt, daß typeOf ab JS 1.1, === erst ab JS 1.2 vorhanden sind und somit in älteren Versionen Fehler erzeugen.
Gruß, Cybaer
gruss Cybaer,
Der Vollständigkeit sei nach erwähnt, daß typeOf ab JS 1.1, === erst ab JS 1.2 vorhanden sind und somit in älteren Versionen Fehler erzeugen.
wann stoesst man denn heute noch auf einen client,
der aelter als netscape navigator 3 oder msie 3 ist?
(,denn JavaScript 1.1 bzw. JScript1 und damit auch der
operator typeof wurden dort jeweils schon unterstuetzt)
by(t)e by(t)e - peterS. - pseliger@gmx.net
Hi,
wann stoesst man denn heute noch auf einen client,
der aelter als netscape navigator 3 oder msie 3 ist?
(,denn JavaScript 1.1 bzw. JScript1 und damit auch der
operator typeof wurden dort jeweils schon unterstuetzt)
Das weiß man nicht. Oder hättest Du gewußt, daß der integrierte Browser eines *neuen* PalmOS-Keyboards mit WLAN (Mischung zw. PalmTop und vollwertiger Tastatur - s. aktuelle c't) zwar JavaScript beherrscht, aber nur JS 1.3?
Auch bei einigen Unis/Behörden/Firmen/Otto-Normal-Usern gibt es eigentlich veraltete Browser (sogar den IE 3, weil der bei einer Win95-Version dabei war - sogar in der Erst-Verson mit JS 1.0).
Man muß ja nicht unbedingt darauf Rücksicht nehmen (kommt auch auf die Zielgruppe an), aber man darf sich dessen wenigstens bewußt sein - schadet ja nicht. IMHO sollte man allerdings generell seine Scripte so bauen, daß sie keine Fehler produzieren. Das schließt die Nutzung von neueren und neuesten Funktionen ja auch überhaupt nicht aus ...
Gruß, Cybaer
hallo again Cybaer,
Man muß ja nicht unbedingt darauf Rücksicht nehmen ... aber man
darf sich dessen wenigstens bewußt sein ... IMHO sollte man
allerdings generell seine Scripte so bauen, daß sie keine Fehler
produzieren. Das schließt die Nutzung von neueren und neuesten
Funktionen ja auch überhaupt nicht aus ...
volle zustimmung - tschoe - peterS. - pseliger@gmx.net