Enrico: Test auf array funktioniert nicht wie beabsichtigt

Hallo,

bezüglich der Erzeugung der Menüstruktur unseres Webshops bin ich nun auf JavaScript umgeschwenkt, um in der endgültigen Fassung unnötige Reloads der Seite zu vermeiden.

Hierbei habe ich folgende (gekürzte) Struktur:

var Hauptmenue = ["Warenkorb", "Wir über uns", "Rüstzeug", "Waffen", "Sonderangebote", "Anfrage"],  
  
    WirUeberUns = ["Neuigkeiten", "Geschichte", ...],  
    Ruestzeug   = ["Für den Kopf", "Für den Oberkörper", ...],  
    Waffen      = ["Speere", "Hämmer", "Äxte", ...],  
  
    Suche       = ["Suche", "Detailsuche", "Hilfe", "Sitemap"];

Wie ersichtlich ist/sein sollte, gibt es nicht zu allen Hauptmenüpunkten auch ein Untermenü.

Um nun zu testen, ob ein Hauptmenüpunkt ein Untermenü enthält, nehme ich folgenden Code:

function istArray (Wert)  
{  
   Wert = TextBereinigen (Wert);  
  
   return (typeof Wert != "undefined") ? (typeof (Wert.length) == "undefined") ? false : true : false;  
}  
  
function TextBereinigen (Wert)  
{  
   Wert = Wert.replace(/Ä/g, "Ae").replace(/ä/g, "ae").replace(/Ö/g, "Oe").replace(/ö/g, "oe").replace(/Ü/g, "Ue").replace(/ü/g, "ue").replace(/ß/g, "ss");  
  
   if (Wert.indexOf(" ") != -1)  
   {  
      var Woerter = Wert.split(" "),  
          w       = Woerter.length,  
          x       = 0,  
          Wert    = "";  
  
      for (; x < w; x++)  
      {  
         Woerter[x] = Woerter[x].substr(0, 1).toUpperCase() + Woerter[x].substr(1);  
  
         Wert += Woerter[x];  
      }  
   }  
  
   return Wert.replace(/ /g, "");  
}

Der Test, ob eine so ermittelte Variable tatsächlich ein Array ist, erfolgt über dann über den Aufruf if (istArray (Hauptmenue[x])), wobei ich "x" aus einer for-Schleife erhalte.

Leider ist es aber so, dass ich hier immer eine positive Rückmeldung bekomme und beispielsweise auch der Hauptmenüpunkt "Sonderangebote" ein Untermenü enthält, obwohl das gar nicht der Fall ist.

Ich hatte zunächst vermutet, dass mir die Funktion TextBereinigen ein Array in einen String umwandeln könnte, und bin mir auch jetzt noch nicht sicher, ob das nicht der Fall ist, aber auch wenn ich den Aufruf auskommentiere, bleibt das Ergebnis unverändert.

Was habe ich falsch gemacht?

Danke für eure Hilfe und Gruß,
Enrico

  1. Hi,

    function istArray (Wert)

    {
       Wert = TextBereinigen (Wert);

    return (typeof Wert != "undefined") ? (typeof (Wert.length) == "undefined") ? false : true : false;
    }

      
    Du prüfst hier die Variable Wert - und die ist ein String.  
      
    Du willst aber die Variable prüfen, deren Name in Wert steht.  
      
    Wenn das "globale" Variablen sind, sollten die per window[Wert] greifbar sein.  
      
    
    > Leider ist es aber so, dass ich hier immer eine positive Rückmeldung bekomme  
      
    klar, weil Strings nicht vom typ "undefined" sind, und für Strings ist auch length definiert.  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
  2. var Hauptmenue = ["Warenkorb", "Wir über uns", "Rüstzeug", "Waffen", "Sonderangebote", "Anfrage"],

    WirUeberUns = ["Neuigkeiten", "Geschichte", ...],
        Ruestzeug   = ["Für den Kopf", "Für den Oberkörper", ...],
        Waffen      = ["Speere", "Hämmer", "Äxte", ...],

    Suche       = ["Suche", "Detailsuche", "Hilfe", "Sitemap"];

      
    Ist die Struktur nicht ein wenig unglücklich gewählt?  
      
    ~~~javascript
    menu = [  
    	{  
    		title: "Warenkorb",  
    		url: "/basket",  
    		children: []  
    	},  
    	{  
    		title: "Wir über uns",  
    		url: "/aboutus",  
    		children = [  
    			{  
    				title: "Neuigkeiten",  
    				url: "/aboutus/news",  
    				children: []  
    			},  
    			{  
    				...  
    			}  
    		]  
    	}  
    ]
    

    Eine Klasse wäre wohl noch besser zu handhaben, aber das würde jetzt den Rahmen sprengen.

    So musst du nicht mal prüfen ob ein Menü-Eintrag ein Array ist, sondern nur ob er mind. 1 Unterpunkt hat.
    Und es spart dir auch noch das ganze RegExp-Gewurschtel, was das ganze übersichtlicher machen würde.

    MfG
    bubble

    --
    If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
  3. @@Enrico:

    nuqneH

    var Hauptmenue = ["Warenkorb", "Wir über uns", "Rüstzeug", "Waffen", "Sonderangebote", "Anfrage"],

    WirUeberUns = ["Neuigkeiten", "Geschichte", ...],

      
    BTW, Variablenbezeichner dürfen in JavaScript auch aus Nicht-ASCII-Zeichen bestehen. Wenn du also deutschsprachige Variablenbezeichner verwendest, kannst du sie auch richtig schreiben: `Hauptmenü`{:.language-javascript}, `WirÜberUns`{:.language-javascript}, …  
      
    Qapla'
    
    -- 
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    
  4. Hallo,

    erst mal Danke an euch, die ihr mir geschrieben habt.

    Ich werde aus beruflichen Gründen vermutlich leider erst morgen Abend dazu kommen, mir eure Antworten genauer anzusehen.

    Ich melde mich dann noch mal.

    Gruß,
    Enrico

    1. Hallo,

      so, habe jetzt doch schon eher Zeit gefunden, mir eure Antworten durchzulesen und mich mit dem Problem auseinanderzusetzen.

      Folgendes würde funktionieren, ohne dass ich meine Menüstruktur, wie von bubble vorgeschlagen, ändern muss:

      var Untermenue = TextBereinigen (Hauptmenue[x]);

      try  
      {  
         if (eval ("typeof (Untermenue) != 'undefined'") && eval (Untermenue) instanceof Array)  
        
         // Untermenue vorhanden  
      }  
      catch (err)  
      {  
         // Kein Untermenue vorhanden  
      }
      

      Gruß,
      Enrico

      1. Hallo!

        var Untermenue = TextBereinigen (Hauptmenue[x]);

        try
        {
           if (eval ("typeof (Untermenue) != 'undefined'") && eval (Untermenue) instanceof Array)

        // Untermenue vorhanden
        }
        catch (err)
        {
           // Kein Untermenue vorhanden
        }

          
        Entschuldige bitte, aber deine Lösung ignoriert alle drei Antworten, die dir bisher gegeben wurden.  
          
        Warum verwendest du hier eval()? Es scheint mir unnötig zu sein.  
          
        `eval ("typeof (Untermenue) != 'undefined'")`{:.language-javascript} ist genau dasselbe wie `typeof Untermenue != 'undefined'`{:.language-javascript}. Nur komplexer und langsamer.  
          
        `typeof xyz != 'undefined'`{:.language-javascript} ist nur nötig, wenn du nicht weißt, ob die Variable überhaupt existiert. Da du sie aber mit dem var-Statement in der Zeile davor erzeugt hast, besteht keine Gefahr. Natürlich kann sie den Wert undefined haben, aber die Abfrage `xyz instanceof Array`{:.language-javascript} würde das abdecken.  
          
        `eval(Untermenue)`{:.language-javascript} ist sehr schlechter Programmierstil. Wenn es sich um globale Variablen handelt, wäre `window[Untermenue]`{:.language-javascript} möglich – siehe [MudGuards Posting](https://forum.selfhtml.org/?t=215261&m=1473893).  
          
        ~~~javascript
        var untermenüName = deineFunktion(…);  
        if (window[untermenüName] instanceof Array) {…} else {…}
        

        Wenn das, was Untermenue bezeichnet, keine globale Variable ist, solltest du eine Objektstruktur (einen Hash) verwenden, wie bubble vorschlägt. Dann kannst du einfach objekt[eigenschaft] notieren. Bitte setze dich damit mal auseinander – es ist die bestmögliche Lösung, die letztlich vieles einfacher macht.

        Auch try … catch dürfte damit unnötig werden. Wenn du dir eine globale Variable über window["variablenname"] oder eine Eigenschaft einem eigenen Hash holst und den Wert mit instanceof Array prüfst, wird niemals eine Exception geworfen. Bei fast allen Abfragen in JavaScript ist try … catch unnötig, macht die Ausführung langsamer und das Debugging schwerer. Siehe meinen Artikel Objektabfragen und Fallunterscheidungen in JavaScript.

        Bitte reagiere auf die Vorschläge, die dir hier gemacht werden. Sie sollen helfen, einfachen und robusteren Code zu schreiben, sodass Umwege wie eval() und try…catch, die zurecht als schlechte Coding-Praxis angesehen werden, nicht nötig sind.

        Grüße,
        Mathias