Gast: JSON Javascript Scopes

Hallo,
ich arbeite mich gerade in den Titel genanntes Thema ein und habe ein Problem:
Wieso klappt dieser Code nicht:

$(document).ready(function(){  
	var start = new Start();  
});  
  
var Start = function(){  
	var objects = [];  
	  
	jQuery.getJSON("json/objects.json", function(data){  
		Start.objects = data;  
	});  
	  
	for(var i=0; i<objects.length; i++){  
		console.log(objects[i]);  
	}  
	  
};

Er sollte mit den Inhalt meiner JSON Datei ausgeben..

  1. Hi,

    Wieso klappt dieser Code nicht:

    Was klappt denn daran nicht?

    $(document).ready(function(){

    var start = new Start();
    });

    var Start = function(){
    var objects = [];

    jQuery.getJSON("json/objects.json", function(data){
    Start.objects = data;
    });

    for(var i=0; i<objects.length; i++){
    console.log(objects[i]);
    }

    };

    
    >   
    > Er sollte mit den Inhalt meiner JSON Datei ausgeben..  
      
    Die Schleife ist außerhalb des Success-Handlers und läuft daher zu einem Zeitpunkt, wo (höchstwahrscheinlich) die Server-Antwort noch nicht vorhanden ist. Start.objects ist daher zum Zeitpunkt, an dem die Schleife abgearbeitet wird, leer.  
      
    Bis die Tage,  
    Matti
    
    -- 
    [Webapplikationen in C++ entwickeln](http://tntnet.org/)
    
    1. Cool danke für die Antwort. Das war der Fehler.
      Jetzt habe ich ein anderes Problem:

      $(document).ready(function(){  
      	new Start();  
      });  
        
      var Start = function(){  
      	var that = this;  
      	var text ="test";  
      	  
      	 jQuery.getJSON("json/objects.json", function(data){  
      		that.draw(text, data);  
      	});  
      };  
        
      Start.prototype.draw = function(text, data){  
        
      	alert(text);  
      };
      

      Anscheinend kann ich text nur in der prototype funktion aufrufen, wenn ich es als parameter in der callback funktion mit übergebe. Gibt es einen besseren Weg mit einem prototype auf die variable der Klasse Start text zuzugreifen?

      1. Hi,

        ich empfehle dir mal Molilys JavaScript-Guide, der beantwortet solche Fragen.

        $(document).ready(function(){

        new Start();
        });

        var Start = function(){
        var that = this;
        var text ="test";

        jQuery.getJSON("json/objects.json", function(data){
        that.draw(text, data);
        });
        };

        Start.prototype.draw = function(text, data){

        alert(text);
        };

        
        >   
        > Anscheinend kann ich text nur in der prototype funktion aufrufen, wenn ich es als parameter in der callback funktion mit übergebe. Gibt es einen besseren Weg mit einem prototype auf die variable der Klasse Start text zuzugreifen?  
          
        Einfache Antwort (ein JavaScript-Guru wird sie dir besser beantworten können):  
        that ist im Kontext des neuen Start-Objektes kein Member, sondern nur eine private Variable des Konstruktors.  
        Um that zu einem Klassenmember zu machen, müsstest du es als this.that identifizieren.  
          
        Bis die Tage,  
        Matti
        
        -- 
        [Webapplikationen in C++ entwickeln](http://tntnet.org/)
        
        1. that ist im Kontext des neuen Start-Objektes kein Member, sondern nur eine private Variable des Konstruktors.
          Um that zu einem Klassenmember zu machen, müsstest du es als this.that identifizieren.

          Du meinst text, that ist ja genau dazu da, den Objektbezug der Closure zu speichern.

          1. Hallo,

            that ist im Kontext des neuen Start-Objektes kein Member, sondern nur eine private Variable des Konstruktors.
            Um that zu einem Klassenmember zu machen, müsstest du es als this.that identifizieren.

            Du meinst text, that ist ja genau dazu da, den Objektbezug der Closure zu speichern.

            Aber wo ist der Sinn, die Funktion prototypisch zu definieren, statt innerhalb der Klasse?

            Warum überhaupt eine Klasse mit "new"?

            Gruß

            jobo

            1. Aber wo ist der Sinn, die Funktion prototypisch zu definieren, statt innerhalb der Klasse?

              Hier im speziellen? Allgemein kannst du über den Prototypen ohne den Konstruktor zu ändern zusätzliche Eigenschaften an einem Objekttyp hinterlegen. Auch an bereits mit new angelegte Instanzen.
              Du musst die Eigenschaften nur einmal an dem Prototyp speichern, nicht jedesmal beim Anlegen einer Instanz, was aber auch wieder Probleme verursachen kann.

            2. Aber wo ist der Sinn, die Funktion prototypisch zu definieren, statt innerhalb der Klasse?

              Wo ist der Sinn von prototypischer Vererbung überhaupt? Die Wiederverwendung von Objekten. Methoden müssen nur einmal angelegt werden. Beim funktionalen Erzeugen von Objekten, ob in einer normalen Funktion oder einer Funktion, die mit new aufgerufen wird, werden Methoden immer wieder neu erzeugt.

              http://molily.de/weblog/closures-performance
              http://jsperf.com/private-or-not-private/3

              Private Objekte haben also ihre Kosten.

              Warum überhaupt eine Klasse mit "new"?

              Das ist noch einmal eine andere Frage, Leute wie Crockford plädieren ja für rein prototypische und funktionale Object Composition. Durchgesetzt hat sich das nicht und ich bin bei den größeren Systemen, an denen ich entwickle, sehr froh über pseudoklassische Vererbung (konkret Pseudoklassen mit CoffeeScript).

              Natürlich kann man das auch ohne Konstruktoren lösen, die mit new aufgeruen werden, und Features wie super-Calls kann man auch besser mit Object Composition lösen:

              http://uxebu.com/blog/2011/02/23/object-based-inheritance-for-ecmascript-5/
              http://www.2ality.com/2011/06/prototypes-as-classes.html
              https://github.com/kriszyp/compose

              Allerdings sehe ich beim pseudoklassischen Konzept keine schwerwiegenden Nachteile, außer vielleicht dass die Versteifung auf große Klassenhierarchien und super-Calls stark eingeschränkt. Funktionale Programmierung und Object Composition sollte man also nicht über Bord werfen.

              Mathias

      2. Hallo,

        Cool danke für die Antwort. Das war der Fehler.
        Jetzt habe ich ein anderes Problem:

        $(document).ready(function(){

        new Start();
        });

        var Start = function(){
        var that = this;
        var text ="test";

        jQuery.getJSON("json/objects.json", function(data){
        that.draw(text, data);
        });
        };

        Start.prototype.draw = function(text, data){

        alert(text);
        };

          
        was genau willst du denn machen?  
          
        Gruß  
          
        jobo
        
      3. $(document).ready(function(){

        new Start();
        });

        var Start = function(){
        var that = this;
        var text ="test";

        jQuery.getJSON("json/objects.json", function(data){
        that.draw(text, data);
        });
        };

        Start.prototype.draw = function(text, data){

        alert(text);
        };

        
        >   
        > Anscheinend kann ich text nur in der prototype funktion aufrufen, wenn ich es als parameter in der callback funktion mit übergebe. Gibt es einen besseren Weg mit einem prototype auf die variable der Klasse Start text zuzugreifen?  
          
        Allgemein: Es gibt in JavaScript keine Klassen. JavaScript ist eine funktionale Sprache. Es gibt Konstruktoren, das sind Funktionen, und Prototypen, das sind einfache Objekte.  
          
        Es gibt keine »privaten Eigenschaften« in JavaScript, wie man es aus klassenbasierten Sprachen kennt. Es gibt Objekteigenschaften an der Instanz direkt oder »vererbte« Eigenschaften an einem der Prototypen.  
          
        Variablen-Gültigkeitsbereiche (Scopes) werden in JavaScript (ECMAScript 3, 5) einzig und allein durch Funktionen erzeugt.  
          
        Konstruktoren sind Funktionen, sodass die »text« eine einfache lokale Funktionsvariable ist. Sie ist nur in dieser Funktion und verschachtelten Funktionen zugänglich.  
          
        Sie ist nichts besonderes dadurch, dass sie in einem Konstruktor erzeugt wurde. Es gibt keine Regel, dass aus dieser einfachen Funktionsvariable eine »private Eigenschaft« der Instanz wird, die aufgrund irgendeiner Regel für Methoden am Prototyps zugänglich wäre.  
          
        Entweder du verwendest hier eine normale »öffentliche« Eigenschaft des Instanzobjekts oder du verschachteltest die Funktion in der Konstruktorfunktion, anstatt sie am Prototyp zu erzeugen.  
          
        ~~~javascript
        function Konstruktor () {  
          this.eigenschaft = 'foo';  
        }  
          
        this.methode = function () { alert(this.eigenschaft); };
        

        oder

        function Konstruktor () {  
          var privat = 'foo';  
          this.priviligierteMethode = function () { alert(privat); };  
        }
        

        Mathias