molily: Operatoren und Typumwandlungen, war: Klausur-Spickzettel

Hallo,

dieses Posting ist eine Antwort auf einen gelöschten Spickzettel, an dem sich verschiedene häufige JavaScript-Missverständnisse zeigen lassen.

<html>

Davor fehlt die DOCTYPE-Angabe:
<!DOCTYPE html>

var a = parseFloat(Zahl1.value);
                 var b = 0;
                 if (a<b){

parseFloat ist hier unnötig, der Operator < wandelt die Operanden mittels Number() (intern ToNumber) in Number-Werte um, ausgenommen beide Operanden sind Strings.

ToNumber ist dabei allerdings nicht so fehlertolerant wie parseFloat; wenn z.B. Buchstaben nach der Zahl folgen, kommt NaN heraus:
parseFloat(" 123.4asdf ") ergibt 123.4
Number(" 123.4asdf ") ergibt NaN wegen dem »asdf«, die Leerzeichen sind okay

Beide können keine Zahlen mit Kommas als Dezimaltrenner parsen:
"123,4" > 0 ergibt false, weil Number("123,4") NaN ergibt.

Eingabewerte zuverlässig umwandeln kann man also mit beide nicht!

(Quellen: Abstract Relational Comparison Algorithm, parseFloat, ToNumber ff.)

if (a==b){

Wenn beim Vergleichsoperator == ein Operand eine Number ist, dann wird der andere Wert automatisch in Number umgewandelt. Auch hier ist keine explizite Typumwandlung nötig.

(Quellen: Abstract Equality Comparison Algorithm, JS Coercion Tool)

function FensterOeffnen (TF1){
            var MeinFenster = window.open("","Zweitfenster",
                              "width=300,height=200,scrollbars=yes");

Popup-Fenster sind nicht mehr zeitgemäß. Wieso wird euch das beigebracht? So etwas hat man vor 10 Jahren gemacht. DOM-Manipulationen wären angebracht. Eine angemessene Aufgabe wäre: Geben Sie den Wert in einem Element unterhalb des Formulars aus.

MeinFenster.document.write("<html><head><title>neues Fenster</title></head>");
            MeinFenster.document.write("<body bgcolor='#00ff00'>")
            MeinFenster.document.write("<p align='center'>");

Attribute zur direkten Beeinflussung der Präsentation wie bgcolor und align sind schlechter Stil, das vergisst du am besten gleich wieder. Formatierungen nimmt man mit ausgelagertem CSS vor. Da ihr SELFHTML benutzen dürft: http://de.selfhtml.org/css/@title=http://de.selfhtml.org/css/

MeinFenster.document.write("Hallo<br>");
            MeinFenster.document.write(TF1.value)
            MeinFenster.document.write("</p>");
            MeinFenster.document.write("</body>");
            MeinFenster.document.write("</html>");

Wie wäre es, den String zuerst zusammenzubauen und dann mit *einem* write-Aufruf in das Fenst zu schreiben. Außerdem wäre der Aufruf von http://de.selfhtml.org/javascript/objekte/document.htm#open@title=document.open und http://de.selfhtml.org/javascript/objekte/document.htm#close@title=document.close angebracht.

<script language="javascript">

Es sollte <script type="text/javascript"> heißen, oder du lässt sämtliche Attribut weg, wenn du HTML5 schreibst.

function fkt( ){

Eine Funktion solltest du nie »fkt« nennen sondern danach, was sie tut.

var i=0
         while (i<100){
         var
         MeinFenster = window.open("","Zweitfenster",
                              "width=300,height=200,scrollbars=yes");

Hier rufst du 100 mal window.open auf. Das ist Quatsch, dieser Aufruf darf nicht in die Schleife.

i=i+1;
            if (i%6 !=0){
            if (i%10 !=6){
            if (parseInt (i/10)%10 !=6){

Welchen Zweck erfüllt das? Schließe 60 bis 69 aus? Das ginge auch einfacher.

MeinFenster.document.write(i);
                 MeinFenster.document.write("<br>");
                 MeinFenster.document.write("<html>");
                 MeinFenster.document.write("<body bgcolor='003300' text='C0B2C0'>");
                 MeinFenster.document.write("</body>");
                 MeinFenster.document.write("</html>");

Hier schreibst du 100 Mal ein neues Dokument ins Fenster, zumal in einer verquerten Reihenfolge. Die Ausgabe von <html><body> muss vor die Schleife und die Ausgabe von </body></html> danach.

<html>
<head>
<script language="javascript">
   function Rechnung(Anz1,Anz2,GPreis1,GPreis2,EPreis1,EPreis2,Summe){
   GPreis1.value=parseFloat(Anz1.value)*parseFloat(EPreis1.value);
   GPreis2.value=parseFloat(Anz2.value)*parseFloat(EPreis2.value);
   Summe.value=parseFloat(GPreis1.value)+parseFloat(GPreis2.value);

Der Operator * wandelt automatisch alle Operanden in Number-Werte um. Wenn du hier Variablen für die Zwischenwerte verwenden würdest, kannst du dir auch das parseFloat sparen. (Dort ist es ansonsten angebracht, weil + Strings verkettet, sobald ein Operand ein String ist.)

Grüße,
Mathias

  1. Gib's ihnen ;)

    Ich reiche folgendes nach:

    i=i+1;

    Eleganter ist hier sicher ein <http://de.selfhtml.org/javascript/sprache/operatoren.htm@title=entsprechender Operator> damit man auf einen Blick sieht, dass die der Wert hochgezählt wird. Bei der notierten Variante muss ich zumindest einen Bruchteil einer Sekunde nachdenken.

    i++;

    1. i=i+1;

      Eleganter ist hier sicher

      ... eine konventionelle for-Schleife, die Deklaration der Laufvariable, Laufbedingung und Erhöhen des Schleifenzählers in einer Zeile abfrüstückt. In dem Kontext schreibt man üblicherweise i++:

      for (var i = 0; i < 100; i++) { ... }  
      
      
      1. i=i+1;

        Eleganter ist hier sicher

        ... eine konventionelle for-Schleife, die Deklaration der Laufvariable, Laufbedingung und Erhöhen des Schleifenzählers in einer Zeile abfrüstückt. In dem Kontext schreibt man üblicherweise i++:

        for (var i = 0; i < 100; i++) { ... }

          
        Das sowieso :)
        
  2. Moin,

    Popup-Fenster sind nicht mehr zeitgemäß. Wieso wird euch das beigebracht? So etwas hat man vor 10 Jahren gemacht. DOM-Manipulationen wären angebracht. Eine angemessene Aufgabe wäre: Geben Sie den Wert in einem Element unterhalb des Formulars aus.

    Man kann nicht generell davon ausgehen, dass Popups IMMER schlecht sind.
    Ich gebe Dir recht, für einen Zweck wie diesen wäre etwas wie ein Layer oder eine andere Art von DOM-Manipulation inzwischen angebrachter.

    Es gibt aber Anwendungsfälle und Vorgaben, bei denen man Popups leider braucht (Beispiel: Im "Popup" soll eine Domain-fremde Seite geöffnet werden, und zwar in einer vorher definierten Größe - wie will man das sinnvoll hinkriegen, ohne sich mit AJAX & Co völlig zu verbiegen?)
    Ich sage nicht dass das schön ist, nur dass das von Kunden eben oft genauso gefordert wird oder nicht anders realisierbar ist ("Wir können in unserem CSS nur Popups verlinken..." etc.). Da hilft nur dagegen argumentieren, Vorschläge machen, wie mans eleganter lösen könnte - aber oft landet man dann halt eben doch wieder beim Popup.

    -> Insofern sollte jemand, der Web-Technologien erlernt, sowas mal gesehen haben (und idealerweise zusätzlich wissen, dass es anders besser geht). Genauso wie jemand wissen sollte, wie man eine HTML-Tabelle baut, auch wenn die Bedeutung auf Grund der zeitgemäßeren Formatierungen mit CSS nachgelassen hat.

    Zu dem Rest was du schriebst: Full Ack!

    Viele Grüße,
    Jörg

    1. ("Wir können in unserem CSS nur Popups verlinken..." etc.)

      Äh "CMS" sollte das natürlich heissen :)

    2. Es gibt aber Anwendungsfälle und Vorgaben, bei denen man Popups leider braucht (Beispiel: Im "Popup" soll eine Domain-fremde Seite geöffnet werden, und zwar in einer vorher definierten Größe - wie will man das sinnvoll hinkriegen, ohne sich mit AJAX & Co völlig zu verbiegen?)

      Mit einem iframe.

      Struppi.

      1. Hallo,

        Mit einem iframe.

        Du umgehst eine veraltete, unschöne Technologie mit einer anderen veralteten unschönen Technologie? Hervorragend ;)

        Grüße,
        Jörg

        1. Mit einem iframe.
          Du umgehst eine veraltete, unschöne Technologie mit einer anderen veralteten unschönen Technologie? Hervorragend ;)

          Wie kommst du darauf?

          Gegen iframes gibt es nichts zu sagen, sie sind weder veraltet (ist auch im HTML5 Standard) noch unschön. Sie sind sogar die einzige Möglichkeit mit HTML ein Dokument eines fremden Servers einzubinden. Daher auch in JS optimal für den von dir geschilderten Zweck.

          Struppi.

          1. Mit einem iframe.

            Sie sind sogar die einzige Möglichkeit mit HTML ein Dokument eines fremden Servers einzubinden.

            object? :)

            1. Mit einem iframe.

              Sie sind sogar die einzige Möglichkeit mit HTML ein Dokument eines fremden Servers einzubinden.

              object? :)

              Stimmt, da hab' ich nicht dran gedacht.

              Struppi.

  3. Hi,

    i=i+1;
                if (i%6 !=0){
                if (i%10 !=6){
                if (parseInt (i/10)%10 !=6){

    Welchen Zweck erfüllt das? Schließe 60 bis 69 aus?

    Nein. Schließe durch 6 teilbare Werte aus sowie solche, deren erste oder zweite Ziffer 6 ist.

    Erinnert irgendwie an das Spiel, wo reihum jeder die nächste Zahl sagen muß, aber wann immer eine 6 vorkommt (als Faktor oder Ziffer) statt der Zahl ein Ersatzwort gesagt werden muß.
    Und wer einen Fehler macht, wird irgendwie bestraft ...

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
    1. Hi Mudguard.

      i=i+1;
                  if (i%6 !=0){
                  if (i%10 !=6){
                  if (parseInt (i/10)%10 !=6){

      Welchen Zweck erfüllt das? Schließe 60 bis 69 aus?

      Nein. Schließe durch 6 teilbare Werte aus sowie solche, deren erste oder zweite Ziffer 6 ist.

      Durch sechs teilbare Werte und solche, deren *letzte* oder *vorletzte* Ziffer eine Sechs ist.

      Erinnert irgendwie an das Spiel, wo reihum jeder die nächste Zahl sagen muß, aber wann immer eine 6 vorkommt (als Faktor oder Ziffer) statt der Zahl ein Ersatzwort gesagt werden muß.

      Daran habe ich auch gedacht :-)

      Viele Gruesse,
      der Bademeister

      1. Hi,

        i=i+1;
                    if (i%6 !=0){
                    if (i%10 !=6){
                    if (parseInt (i/10)%10 !=6){

        Welchen Zweck erfüllt das? Schließe 60 bis 69 aus?

        Nein. Schließe durch 6 teilbare Werte aus sowie solche, deren erste oder zweite Ziffer 6 ist.

        Durch sechs teilbare Werte und solche, deren *letzte* oder *vorletzte* Ziffer eine Sechs ist.

        Ich habe das
        while (i<100){
        gleich mitberücksichtigt ;-)

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
        1. Ich habe das
          while (i<100){
          gleich mitberücksichtigt ;-)

          Ah, da kann ich jetzt wohl wenig gegen sagen. Ich ziehe meinen Einwand zurück :-)

          Viele Grüße,
          der Bademeister