Linuchs: TypeError: obj.style is undefined

Moin,

nach dem Laden eines Bildes möchte ich es ansprechen. Warum kann ich keinen style zuweisen?

<img id=utkiek class=webcam style="display:block" src="http://utkiek.vege.net/record/current.jpg">
window.addEventListener('load', function ( ) {
  // Web-Bilder finden
  obj = document.getElementsByClassName( "webcam" );
  alert ( "[" +obj.length +"] Web-Bilder" ); // meldet 1 Bild
  for ( i=0; i<obj.length; i++ ) {
    obj.style.border = "1px solid #000";
    obj.style.padding = "2px";
  }
});

Fehlermeldung: TypeError: obj.style is undefined

Linuchs

  1. Hallo Linuchs,

    window.addEventListener('load', function ( ) {
      // Web-Bilder finden
      obj = document.getElementsByClassName( "webcam" );
      alert ( "[" +obj.length +"] Web-Bilder" ); // meldet 1 Bild
      for ( i=0; i<obj.length; i++ ) {
        obj.style.border = "1px solid #000";
        obj.style.padding = "2px";
      }
    });
    

    Fehlermeldung: TypeError: obj.style is undefined

    Es fehlt der Index. obj.style vs obj[i].style.

    LG,
    CK

    1. Es fehlt der Index. obj.style vs obj[i].style.

      Au weia ... Brett vorm Kopf. Danke.

      Linuchs

  2. Hallo,

    Warum kann ich keinen style zuweisen?

    Weil obj nicht dein Bild ist, sondern die Liste deiner Bilder.

    Gruß
    Kalk

  3. Tach!

    nach dem Laden eines Bildes möchte ich es ansprechen. Warum kann ich keinen style zuweisen?

    Eine HTMLCollection hat keine Eigenschaft style.

      obj = document.getElementsByClassName( "webcam" );
      for ( i=0; i<obj.length; i++ ) {
        obj.style.border = "1px solid #000";
    

    Anscheinend weißt du ja, dass getElementsByClassName() sowas ähnliches wie ein Array liefert, aber du sprichst die einzelnen Elemente nicht an.

    dedlfix.

    1. Tach!

      Browser haben Entwicklertols eingebaut. Wenn man den Fehler nicht durch Code-Betrachten erkennt, kann man immerhin nachschauen, was wirklich in einer Variable enthalten ist.

      dedlfix.

  4. Hallo Linuchs

    window.addEventListener('load', function ( ) {
      // Web-Bilder finden
      obj = document.getElementsByClassName( "webcam" );
      alert ( "[" +obj.length +"] Web-Bilder" ); // meldet 1 Bild
      for ( i=0; i<obj.length; i++ ) {
        obj.style.border = "1px solid #000";
        obj.style.padding = "2px";
      }
    });
    

    Abgesehen von dem, was die anderen bereits gesagt haben: Mir ist in deinem Code aufgefallen, sowohl in diesem Thread also auch im Letzten, dass du offenbar jede Menge globale Variablen produzierst, da du konsequent das Schlüsselwort var auslässt.

    // globale Variable obj
    obj = document.getElementsByClassName( "webcam" );
    
    // globale Variable i
    for ( i=0; i<obj.length; i++)
    

    Jede Zuweisung die du vornimmst ohne die Variable lokal zu deklarieren erzeugt eine globale Variable, also eine Eigenschaft des Objektes window, womit du völlig unnötig das Risiko von Namenskonflikten schaffst. Das heißt, du solltest deine Variablen vor der Verwendung immer deklarieren, also bei der Erzeugung der Variable das Schlüsselwort var notieren.

    var obj = document.getElementsByClassName('webcam');
    
    for (var i = 0; i < obj.length; i ++) // ...
    

    Um dich dagegen zu schützen, versehentlich globale Variablen zu produzieren, kannst und solltest du dein Programm – oder zumindest einzelne Funktionen – im Strict Mode ausführen. Wenigstens in der Entwicklungsphase. Wenn du dann das Schlüsselwort var vergisst wird eine Ausnahme geworfen und du kannst den Fehler sofort korrigieren.

    function safe ( ) {
      'use strict';
      foo = 42;
    }
    
    safe( ); // Error - assignment to undeclared variable foo
    

    Gruß,

    Orlok

    1. Hallo Orlok

      Jede Zuweisung die du vornimmst ohne die Variable lokal zu deklarieren erzeugt eine globale Variable, also eine Eigenschaft des Objektes window, womit du völlig unnötig das Risiko von Namenskonflikten schaffst. Das heißt, du solltest deine Variablen vor der Verwendung immer deklarieren, also bei der Erzeugung der Variable das Schlüsselwort var notieren.

      Danke für den Hinweis.

      Da ich oft mehrere Javascript-Dateien einbinde, sollte ich wohl auch deren "globale" Variablen - die ja dann auch für die anderen Skripte gelten - mit einem Vornamen versehen, also web_imgUrl statt imgUrl in der Datei webcam.js.

      function safe ( ) {
        'use strict';
        foo = 42;
      }
      
      safe( ); // Error - assignment to undeclared variable foo
      

      Danke auch für den Tipp, habe ich schon ausprobiert.

      Linuchs

      1. Hallo Linuchs,

        Da ich oft mehrere Javascript-Dateien einbinde, sollte ich wohl auch deren "globale" Variablen - […] - mit einem Vornamen versehen,

        Nö. Auf globale Variablen verzichten.

        - die ja dann auch für die anderen Skripte gelten -

        Wenn verschiedene Skripte auf dieselbe Variable zugreifen sollen, müssen es tatsächlich globale Variablen sein, falls du sie nicht als Parameter übergeben kannst. Dann kannst du sie aber auch als window.linuchs_foo anlegen, da sieht dann jeder, wies gemeint ist.

        Bis demnächst
        Matthias

        --
        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
        1. Hallo Matthias,

          Da ich oft mehrere Javascript-Dateien einbinde, sollte ich wohl auch deren "globale" Variablen - […] - mit einem Vornamen versehen,

          Nö. Auf globale Variablen verzichten.

          Wie soll das denn gehen, wenn mehrere Funktionen in einer .js Datei dieselben Variablen brauchen?

          Soweit ich weiss, kann man z.B. setTimeout für die aufgerufene Funktion keine Variablen mitgeben, die müssen also schon mal global sein.

          Oder gibt es "regionale" Variablen, die nur in einer .js Datei gelten?

          Linuchs

          1. Hallo

            Da ich oft mehrere Javascript-Dateien einbinde, sollte ich wohl auch deren "globale" Variablen - […] - mit einem Vornamen versehen,

            Nö. Auf globale Variablen verzichten.

            Wie soll das denn gehen, wenn mehrere Funktionen in einer .js Datei dieselben Variablen brauchen?

            Warum stellst du hier diese Frage, die Matthias im von dir nur teilweise zitierten Vorposting einen Absatz später beantwortet?

            Zitat: „Wenn verschiedene Skripte auf dieselbe Variable zugreifen sollen, müssen es tatsächlich globale Variablen sein, falls du sie nicht als Parameter übergeben kannst.“

            Das heißt im Umkehrschluss aber auch, dass Variablen, die nicht von verschiedenen Skripten geteilt werden sollen, nicht global sein müssen und sollen. Das trifft meist für den überwiegenden Teil der Variablen zu.

            Tschö, Auge

            --
            Wo wir Mängel selbst aufdecken, kann sich kein Gegner einnisten.
            Wolfgang Schneidewind *prust*
          2. Tach!

            Soweit ich weiss, kann man z.B. setTimeout für die aufgerufene Funktion keine Variablen mitgeben, die müssen also schon mal global sein.

            Da weißt du nicht ganz richtig: MDN zu setTimeout(). Allerdings ist die erste Form nicht in älteren IEs verfügbar. Aber auch dann gibt es keinen Zwang, globale Variablen zu verwenden.

            Oder gibt es "regionale" Variablen, die nur in einer .js Datei gelten?

            Scope, nicht Datei, ist das richtige Stichwort, beispielsweise IIFE. Aber auch jede "normale" Funktion bildet einen Scope. Und sich darin neben dem setTimeout() auch die Callback-Fuktion befindet, so hat man darin Zugriff auf alle Variablen in diesem Scope.

            dedlfix.

            1. Dafür musst Du nicht zur "Konkurrenz" verweisen ;-).

              Das steht - naja, nicht ganz so ausführlich - auch bei uns: setTimeout. Ich habe den Eintrag gerade noch um einen IE Hinweis erweitert.

          3. Ja, sowas wie regionale Variablen gibt es. Die Funktionen, die Du in der .js hast, sind dann allerdings auch regional. Wenn Du das nicht willst, brauchst Du EIN globales Objekt, an das Du die Funktionen als Eigenschaften anklebst.

            Schau Dir im Wiki mal das Revealing Module Pattern an.

            Gruß Rolf

          4. Nö. Auf globale Variablen verzichten.

            Wie soll das denn gehen, wenn mehrere Funktionen in einer .js Datei dieselben Variablen brauchen?

            Neben der bereits von den anderen skizzierten "best practice" ein Kompromissvorschlag, wie Du bei Deinen globalen Variablen bleiben kannst und dabei weitgehend die Verschmutzung des globalen Namensraums vermeiden kannst: pack einfach alles in eine globale Variable:

            window.linuchsGlobals = window.linuchsGlobals || {};
            window.linuchsGlobals.ersteVar = 15;
            window.linuchsGlobals.zweiVar = 'foo';
            window.linuchsGlobals['foo'] = 'bar';
            

            Dann hast Du weiterhin überall globalen Zugriff, aber den globalen Namensraum selber immerhin nur mit einer Variablen verschmutzt: "linuchsGlobals".