2011-01-14 5 views
3

Ich lade eine CSV-Datei und analysiere es. und ich möchte, dass das resultierende Array ein Mitglied eines bestimmten Objekts ist, aber es endet undefiniert, da ich das Schlüsselwort "this" nicht korrekt verwende.Javascript scoping Problem

function SimPlayer(){ 

    this.dataset = new Array(); 
    var client = new XMLHttpRequest(); 
    var dset = this.dataset; 

    function handler(){ 
     if(client.readyState == 4){ 
      if(client.status == 200){ 
       //file is done loading 
       //split by lines 
       dset = client.responseText.split("\n"); 
       for(var i=0; i<dset.length; i++){ 
        //split each line by commas 
        dset[i] = dset[i].split(","); 
        //convert to ints 
        for(var j=0; j<dset[i].length; j++){ 
         dset[i][j] = parseInt(dset[i][j]); 
        } 
       } 
       //dset is defined here, no problem. It contains the data from the csv file 
       console.log(dset[0]); 
      } 
     } 
    } 
    client.onreadystatechange = handler; 
    client.open("GET", "http://nathannifong.com/LayerCake/simdata/rec0_i0.csv"); 
    client.send(); 

    this.check = function(){ 
     //does not work because this.dataset will be empty. 
     console.log(this.dataset[0]) 
    } 
} 

nehme ich eine Instanz von SimPlayer erstellen, und rufen Sie später dann überprüfen

foo = new SimPlayer(); 
//....time passes.... 
foo.check(); 

foo.check() verursacht

Uncaught TypeError: Cannot read property '0' of undefined 
(nach der CSV-Datei Zeit zum Laden hatte)

Wie kann ich meinen Code reparieren, so dass dieses in check() die Daten aus der CSV-Datei enthält?

+0

Wo in Ihrem Code setzen Sie alles auf die tatsächliche 'Dataset' Array? – zzzzBov

+0

Auch finden Sie [meine Antwort auf eine andere Frage über Prototypen] (http://stackoverflow.com/questions/4653472/how-do-i-properly-code-a-javascript-property-and-method-using-using- der Prototyp-Spaß/4653667 # 4653667) nützlich. – zzzzBov

+1

Warum ordnen Sie dset.dataset beim Laden nicht statt vorher dset? – leeny

Antwort

2

Sie werden einen Verweis auf die richtige diese Bindung speichern wollen:

var _this = this; 
this.check = function(){ 
    //does not work because this.dataset will be empty. 
    console.log(_this.dataset[0]) 
} 
+0

Das habe ich in den Zeilen versucht: var client = new XMLHttpRequest(); var dset = dieses.dataset; weil ich ursprünglich innerhalb dieses Handlers auf die MLHttpRequest-Instanz und innerhalb des SimPlayer auf die SimPlayer-Instanz referenziert habe. Ich kann nicht auf beide gleichzeitig verweisen, also habe ich versucht, die richtige Bindung zu speichern. Habe ich es falsch gemacht? – Nathan

+0

Gelöst. Ich habe es falsch gemacht. sollte getan haben: var sim = das; function handler() {sim.dataset} anstelle von: var dset = this.dataset; function handler() {dset} – Nathan

+0

Uh, das wird hier korrekt gebunden, weil 'foo.check()' call es auf 'foo' setzt. Das Problem war in der Tat, dass "dset" ** nicht ** ein Verweis auf "this.dataset" war, so dass die Zuweisung innerhalb des Handlers nur den Wert von dset ändern würde :) –

1

Als Alternative Option Sie das folgende Beispiel betrachten kann:

this.check = (function(thus){ 
    return function() {//does not work because this.dataset will be empty. 
     console.log(thus.dataset[0]) 
    }; 
})(this); 

PS: Ich habe nicht gelesen der Originalbeitrag ganz, mein Beispiel - nur ein alternativer Weg für die Antwort. Sie können solchen Code in vielen JavaScript-Beispielen finden. Sie sollten die Verwendung von Schließungen verstehen.