Alex: Funktionen in Objekten

Hallo Leute,
ich habe da ein kleines Problemchen. Ich habe hier ein Objekt und ich würde eine Methode die ich dort habe direkt ausführen:

obj = {  
  arr: [],  
  init: (function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); })()  
}

Ich bekomme aber eine Fehlermeldung: "ReferenceError: obj is not defined".
Was habe ich falsch gemacht?

Grüße,
 Alex

  1. Huhu ;)

    obj = {

    arr: [],
      init: (function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); })()
    }

    
    > Ich bekomme aber eine Fehlermeldung: "ReferenceError: obj is not defined".  
    > Was habe ich falsch gemacht?  
      
    Für mich sieht das nach Syntax-Problem aus ;)  
      
    Und zwar liegt's konkret an der Funktion, richtig wäre  
      
    ~~~javascript
    var obj = {  
      arr: [],  
      init: function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); }  
    }
    

    Das "var" vor "obj" hab ich auch mal mit eingefügt; ich schätze mal, dass das bei dir auch noch fehlt - auch wenn das kein unbedingter Grund des Scheiterns ist. Solltest du obj an anderer Stelle schon definiert haben, kannst das "var" einfach weglassen.

    Die Schreibweise (function() {...})(); wird dazu genutzt, um eine Funktion direkt nach Definition aufzurufen. Innerhalb eines Objekts wird eine Funktionsdefinition aber genutzt, um die Funktion innerhalb des Objekts abzuspeichern (in deinem Fall als obj.init). Diese beiden Anwendungen vertragen sich also nicht wirklich - zumindest wäre mir das neu.

    Was du vielleicht gesucht hast, ist die Möglichkeit, direkt nach Definition des Objekts eine Funktion auszulösen - das wäre dann aber sinnvollerweise der Konstruktor und der macht nur dann Sinn, wenn dein Objekt nicht nur ein statisches Objekt ist, sondern falls daraus Elemente über "new" abgeleitet werden sollen.

    Solltest du wirklich nur statisch das "obj" definieren und dann direkt die Methode "obj.init" aufrufen wollen, würde ich dir einfacherweise folgendes empfehlen:

    var obj = {  
      arr: [],  
      init: function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); }  
    }  
    obj.init();  
    
    

    Grüße,

    RIDER

    --
    Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
    ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
    1. Aloha

      Was du vielleicht gesucht hast, ist die Möglichkeit, direkt nach Definition des Objekts eine Funktion auszulösen - das wäre dann aber sinnvollerweise der Konstruktor und der macht nur dann Sinn, wenn dein Objekt nicht nur ein statisches Objekt ist, sondern falls daraus Elemente über "new" abgeleitet werden sollen.

      Weil ich da nicht ganz präzise formuliert habe - das sähe dann so aus:

      function Objekt () {  
      	this.arr = [];  
      	  
      	for (var i = 0; i < 11; i++) {  
      		this.arr.push(i);  
      	}  
        
      	alert(this.arr.join(' '));  
      }  
        
      obj = new Objekt();
      

      Das macht aber wie schon angedeutet nur dann Sinn, wenn du mehrere Objekte vom Typ "Objekt" bzw. mit Funktionalität eines "Objekt" brauchst - falls nicht benutze die andere Möglichkeit, die ich gepostet hatte.

      Grüße,

      RIDER

      --
      Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
      ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
    2. Hallo,

      Solltest du wirklich nur statisch das "obj" definieren und dann direkt die Methode "obj.init" aufrufen wollen, würde ich dir einfacherweise folgendes empfehlen:

      var obj = {

      arr: [],
        init: function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); }
      }
      obj.init();

        
      Hmm... ich hatte vorher sowas:  
      ~~~javascript
      obj = {  
        init: (function() { alert('Piep'); })()  
      }
      

      Das hat auch soweit funktioniert... So dachte ich, dass ich auch (wie oben) einen flotten Einzeiler machen kann.

      Grüße,
       Alex

      1. Aloha

        Das hat auch soweit funktioniert... So dachte ich, dass ich auch (wie oben) einen flotten Einzeiler machen kann.

        Dass das Beispiel funktioniert, ist auch klar. Was dabei passiert ist, dass eine statische Funktion (die von keiner Variable abhängt) aufgerufen wird und deren Rückgabewert in obj.init gespeichert wird (warum auch immer das sinnvoll sein soll).

        Im anderen Fall notierst du innerhalb einer Objektdefinition eine sofort aufzurufende Funktion, die wiederum auf Eigenschaften desselben Objekts zugreifen soll. Wenn die Funktion direkt nach Definition ausgelöst werden soll, wie soll sie dann auf obj.arr zugreifen, wenn obj noch nichtmal vollständig definiert ist? Denn zu obj gehört ja wieder der Rückgabewert der Funktion, der in obj.init gespeichert werden soll, die aber wiederum auf obj.arr zugreift, was ... -> ich schätze du siehst was ich meine. Das KANN gar nix anderes geben als "obj is not defined".

        Ich verstehe immer noch nicht genau, was die Notation mit

        var obj = { ...  
            init:(function(){})()  
        }
        

        sinnvollerweise bewirken soll. Die Funktion wird dadurch nicht gespeichert (sie wird ja sofort ausgeführt), sondern nur ihr Rückgabewert (der nicht existiert) ... So what??

        Wenn du unbedingt nen schicken Einzeiler willst, dann doch eher so:

        var obj = {  
            arr : []  
        }  
        (function(){...})();  
        
        

        d.h. den Funktionsaufruf raus aus dem Objekt - denn den nicht vorhandenen Rückgabewert speichern zu wollen ist ja sowieso murks. Dadurch vermeidest du auch konsequent jeden "obj not defined"-Fehler ;)

        Grüße,

        RIDER

        P.S.: Ob Einzeiler immer so "schick" sind, da bin ich mir nicht so sicher. Für mich erschweren Einzeiler die Lesbarkeit und das Debuggen des Codes. Es kann Gebiete geben, in denen der Einsatz von Einzeilern sehr sinnvoll ist - nämlich z.B. bei einem Skript was über ein Lesezeichen aufgerufen werden soll. Im Standard-Einsatzgebiet von Javascript (eingebunden auf einer Homepage) erschließt sich mir der Nutzen von Einzeilern grundsätzlich eher nicht. Das ist aber vielleicht auch einfach eine Glaubensfrage, über die man bekanntlich nicht diskutiert ;)

        --
        Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller
        ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
  2. Hallo

    obj = {

    arr: [],
      init: (function() { for (var i = 0; i < 11; i++) obj.arr.push(i); alert(obj.arr.join(' ')); })()
    }

    
    > Ich bekomme aber eine Fehlermeldung: "ReferenceError: obj is not defined".  
      
    Die Ausführungsreihenfolge ist anders als du erwartest. Der JavaScript-Interpreter führt die Funktion aus, bevor das erzeugte Objekt der Variable obj zugewiesen wurde.  
      
    Er muss erst die Funktion ausführen, bevor er das Objekt mit allen Eigenschaften erzeugen und der Variable zuweisen kann. Also kannst du in der Funktion nicht auf obj verweisen.  
      
    Was hier genau abläuft:  
      
    1\. Der Interpreter sieht einen Objektliteral { eigenschaft1: wert1, eigenschaft2: wert2 usw. }  
    2\. Alle Ausdrücke auf Seiten der Werte werden nacheinander berechnet/aufgelöst  
    3\. Das Objekt wird erzeugt und die Werte den Eigenschaften zugewiesen  
    4\. Das Objekt wird weiter verarbeitet in dem Ausdruck, in dem es vorkommt. Hier kommt es in einer Variablenzuweisung vor var obj = {};, also wird eine Variable “obj” angelegt, die auf das Objekt zeigt  
      
    Schreib es also ganz konservativ:  
      
    ~~~javascript
    var obj = {  
      arr: [],  
      init: function() { was auch immer }  
    };  
    obj.init();
    

    grüße
    Ralf