Enrico: TypeError: is not a function

Hallo,

ich erstelle gerade eine Validierung von Formulareingaben über JavaScript und arbeite hier mit einem Array-Objekt "Fehler", dem ich entweder einen Fehler in der Form "Formularfeld" : "Fehlermeldung" übergebe oder aus dem ich einen Fehler, wenn er nicht mehr besteht, rausgelösche:

  
Fehler = {};  
  
function Pflichtfeld (Wert, NameKlartext)  
{  
   if (!Wert || Wert === "" || (typeof Wert.length === "undefined" && Wert.length === 0))  
   {  
      if (!Fehler.contains (NameKlartext))  
      {  
         if (NameKlartext == "Name")  
            Fehler.add ("Name", "Dein Name fehlt");  
         else  
            if (NameKlartext == "Text")  
               Fehler.add ("Text", "Deine Nachricht fehlt");  
            else  
               ...  
      }  
   }  
   else  
      Fehler.remove (NameKlartext);  
}  
  
Array.prototype.contains = function (obj)  
{  
   var i = this.length;  
  
   do  
   {  
      if (this[i] === obj)  
         return i;  
  
      i--;  
   }  
   while (i !== -1)  
  
   return -1;  
}  
  
Array.prototype.add = function (key, value)  
{  
   if (this.contains (key))  
      this[key] = value;  
   else  
   {  
      this.push (key);  
      this[key] = value;  
   }  
}  
  
Array.prototype.remove = function (key)  
{  
   var l = this.length;  
  
   for (var i = 0; i < l; ++i)  
   {  
      if (this [i] == key)  
      {  
         this.splice (i, 1);  
         return true;  
      }  
   }  
  
   return false  
}  

Leider bekomme ich aber die Fehlermeldung "TypeError: Fehler.contains is not a function".

Ich vermute, dass dann die weiteren Methoden "add" und "remove" leider auch nicht funktionieren werden.

Was habe ich falsch gemacht?

Danke und Gruß,
Enrico

  1. Meine Herren,

    ich erstelle gerade eine Validierung von Formulareingaben über JavaScript und arbeite hier mit einem Array-Objekt "Fehler"

    Fehler = {};

      
    Arrays werden in Javascript mit eckigen Klammern oder dem entsrpechenden Konstruktor-Aufruf vorgenommen  
      
    `Fehler = [];`{:.language-javascript}  
    oder  
    `Fehler = new Array();`{:.language-javascript}  
    weit verbreitet Instanzen immer mit einem kleinen Buchstaben beginnen zu lassen und nur Konstruktoren mit einem Großbuchstaben.
    
  2. Hallo Enrico,

    Array.prototype.contains = function (obj)
    {
       var i = this.length;

    do
       {
          if (this[i] === obj)

    das dürfte auch nicht klappen, der Arrayindex läuft von 0 bis length-1

    return i;

    i--;
       }
       while (i !== -1)

    return -1;
    }

    Gruß, Jürgen

    1. Meine Herren,

      das dürfte auch nicht klappen, der Arrayindex läuft von 0 bis length-1

      Zumal es mit indexOf und every schon Methoden geeignete Methoden gibt, um eine solche Funktion zu implementieren.

      --
      Hey Girl,
      i wish you were asynchronous, so you'd give me a callback.
  3. Hallo,

    Ist dir der Unterschied zwischen einem Array und einem Hash/Hashmap bewusst? Deine Beispiele scheinen beides zu verwechseln. Ich würde behaupten, du suchst einen Hash.

    Hashes werden in JavaScript oft mit einem einfachen Object gelöst. Ein Objekt erlaubt die Operationen, die du vornehmen willst, bereits von Haus aus.

    var obj = {};  
    var key = "foo", value = 1;  
    obj[key] = value;  
    alert(obj.hasOwnProperty(key));  
    // oder  
    alert(key in obj);  
    delete obj[key];
    

    Es gibt bald in ECMAScript 6 eine native Map-Implementierung, die sich nachrüsten lässt, wenn einem ein einfaches Objekt nicht ausreicht. So eine Implementierung ist sinnvoller, als Object.prototype oder Array.prototype mit eigenen ungetesteten Methoden zu erweitern.

    Mathias

  4. Hallo,

    danke für eure Antworten.

    Ich habe jetzt folgende Korrekturen vorgenommen:

    • var Fehler = [];
    • if (Fehler.contains (NameKlartext) === -1), da ja -1 zurückgeliefert wird, wenn nichts gefunden wurde

    Zudem habe ich die Methoden "contains" und "add" geändert:

    Array.prototype.contains = function (obj)
    {
       var j = this.length;

    for (var i = 0; i < j; i++)
          if (this[i] === obj)
             return i;

    return -1;
    }

    Array.prototype.add = function (key, value)
    {
       this.push (key);
       this[key] = value;
    }

    Jetzt klappt es auf jeden Fall schon mal.

    @Mathias

    Ist dir der Unterschied zwischen einem Array und einem Hash/Hashmap bewusst?
    Deine Beispiele scheinen beides zu verwechseln

    Meine Änderungen an den Methoden sollten jetzt stimmen, oder was meinst Du?

    Gruß,
    Enrico

    Enrico

    1. Hallo,

      Array.prototype.add = function (key, value)
      {
         this.push (key);
         this[key] = value;
      }

      Ist dir der Unterschied zwischen einem Array und einem Hash/Hashmap bewusst?
      Deine Beispiele scheinen beides zu verwechseln

      Meine Änderungen an den Methoden sollten jetzt stimmen, oder was meinst Du?

      Soweit ich das sehe, lässt sich das, was du zu erreichen versuchst, viel einfacher lösen. Du brauchst keine eigenen Methoden am Array-Prototyp dazu.

      In obiger Methode verwendest du einen Array als Array und gleichzeitig als Hash. Du erzeugt mit push() eine numerische Eigenschaft und speicherst darin den Key, dann setzt du eine weitere Eigenschaft mit Key und Value. Warum dieser Aufwand? Warum nimmst du keinen einfaches Object als Hash?

      Noch einmal zur Erklärung:

      // Object erzeugen  
      var obj = {};  
      // Wert unter Schlüssel speichern  
      var key = "foo", value = 1;  
      obj[key] = value;  
      // Prüfen, ob ein Eintrag unter einem gegebenen Schlüssel existiert  
      alert(obj.hasOwnProperty(key));  
      // oder  
      alert(key in obj);  
      // Eintrag löschen  
      delete obj[key];  
      
      

      Die Prüfung, ob ein Wert unter einem beliebigen Wert existiert, kann über eine for-in-Schleife erfolgen:

      function valueExists (hash, value) {  
        for (var key in hash) {  
          if (hash.hasOwnProperty(key) && hash[key] === value) {  
            return true;  
          }  
        }  
        return false;  
      }
      

      Wobei in deinem Falle das Nachschlagen mit Schlüssel auszureichen scheint.

      Grüße
      Mathias

      1. Hallo Mathias,

        Soweit ich das sehe, lässt sich das, was du zu erreichen versuchst, viel einfacher lösen

        Ich habe es, bereits vor Deiner Antwort, auch einfacher gelöst und jetzt klappt es, nachwievor, einwandfrei, der Code ist aber schlanker.

        Gruß,
        Enrico