0

私は2つのオブジェクトを書きました。1 つは List と呼ばれ、もう 1 つは Car と呼ばれます。

function Car()
{
  this.make="";
  this.year="";
}

function List()
{
  this.cars = [];
}

また、XML ファイルの情報を読み取り、List オブジェクト内の car 配列に格納するオブジェクト List のメソッドである別の関数があります。

List.prototype.readXML = function()
{
  var i = 0;
  $.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(){
      //Bug Point!!!
      this.cars.push(new Car()); //Push a Car object into array
      this.cars[i].ID = ($(this).attr("ID"));
     }); 
   });
 }

ただし、これは機能しません。デバッグで車が定義されていないことが毎回わかります...これの代わりに var を使用して車を定義しようとしました。そして、cars.push の代わりに this.cars.push を削除しようとしました。しかし、それでも車が定義されていないと言っています。

この問題では、変数のスコープに問題がある可能性があると思います。誰かが私にそれを行う方法を教えてもらえますか?

ありがとうございました!

4

3 に答える 3

2

問題はあなたのjqueryにそれぞれあります

$.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(){
      //Bug Point!!!
      this.cars.push(new Car()); //Push a Car object into array
      this.cars[i].ID = ($(this).attr("ID"));
     }); 
   });

thisあなたがそれが参照することを期待するものを参照していません

この問題を克服する一般的な方法は、thatまたはと呼ばれる別の変数に割り当てることです。self

List.prototype.readXML = function()
{
  var i = 0;
  // Create a new variable called 'self' that you can refer to within different function scopes
  var self = this;
  $.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(){
      self.cars.push(new Car()); //Push a Car object into array
      self.cars[i].ID = ($(this).attr("ID"));
     }); 
   });
 }

つまり、アクセスする必要がある元の List オブジェクトにアクセスできるということです。このメソッドはクロージャーを利用します。

お役に立てれば


コメントで尋ねられた説明の質問を編集します。

List.prototype.readXML = function()
{
  // Create a new variable called 'self' that you can refer to within different function scopes
  var self = this;
  $.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(i, domElem){
      var car = new Car();
      car.id = $(domElem).attr("ID");
      self.cars.push(car); //Push a Car object into array
     }); 
   });
 }
于 2012-08-20T22:46:15.523 に答える
1

問題は、このコンテキストがAjaxコールバックで変化することです。プロトタイプでaddCarメソッドを定義し、それを使用して新しい車を追加します。このようなもの:

List.prototype.addCar = function(data) {
  this.cars.push(new Car()); //Push a Car object into array
  this.cars[i].ID = ($(data).attr("ID"));
}

List.prototype.readXML = function()
{
  var i = 0;
  var self = this;
  $.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(){ self.addCar(this); });
   });
 }
于 2012-08-20T22:48:23.827 に答える
1

あなたが抱えている問題は閉鎖に関連しています。

基本的に、この範囲は .each ステートメント内で変更されます。.each は List を参照するのではなく、XML 内の現在の「アイテム」を参照します。

これを修正するには、「JavaScript クロージャはどのように機能しますか?」を参照してください。

List.prototype.readXML = function()
{
  var i = 0;
  var self = this;
  $.get('mydata.xml', function(xml){
    $(xml).find("item").each(function(){
      //Bug Point!!!
      self.cars.push(new Car()); //Push a Car object into array
      self.cars[i].ID = ($(this).attr("ID"));
     }); 
   });
}
于 2012-08-20T22:46:28.380 に答える