2012-01-28 8 views
1

Listというオブジェクトを作成しようとしています。このオブジェクトには、このタスク配列にタスクオブジェクトを単にプッシュするメソッドaddがあります。私はまた、URLからアイテムを読み込むためのロードメソッドを構築しました。Javascriptオブジェクトメソッドの問題

キャッチされない例外TypeError:

私の問題は、私はloadメソッド内からaddメソッドを参照するように見えることはできません、私は次のエラーを取得されたオブジェクトの#は何の方法「を追加」を持っていません。

loadメソッドからaddメソッドを参照するにはどうすればよいですか?私が使用しているコードは以下の通りです。

function List(){ 
    this.tasks = new Array(); 
    this.add = function(taskItem){ 
     this.tasks.push(taskItem); 
    }; 
    this.load = function(url){ 
     $.getJSON(
      url, 
      function(data){ 
       $.each(data, function(key,val){ 
        var task = new Task({ 
         id:val.pkTaskId, 
         title:val.fldName, 
         status:val.fldStatus 
        }); 
        this.add(task); 
       }); 
      } 
      ); 
    } 
} 

var userList = new List(); 
userList.load(url) 

答えて

3

これを試してみてください:

function List(){ 
    this.tasks = []; // prefer [] over new Array() 
    this.add = function(taskItem){ 
     this.tasks.push(taskItem); 
    }; 
    this.load = function(url){ 
     var self = this; 
     $.getJSON(
      url, 
      function (data){ 
       $.each(data, function(key,val){ 
        var task = new Task({ 
         id:val.pkTaskId, 
         title:val.fldName, 
         status:val.fldStatus 
        }); 
        self.add(task); 
       }); 
      } 
     ); 
    } 
} 

問題がthisは、あなたがそれはAjaxのコールバックでと思われるものではないということです。コールバック関数はオブジェクトのコンテキストで呼び出されず、グローバルコンテキストで呼び出されます(thiswindowオブジェクトを指します)。

事前にオブジェクト参照を保存する(慣習的にはself)必要があります。


thisは、必ずしもオブジェクトインスタンスに「所属する」関数を指しているとは限りません。実際、関数は他の言語と同じようにオブジェクトに属しません。 call()またはapply()を使用することによって(

function A() { 
    this.val = "foo"; 
    this.say = function() { alert("A: " + this.val); }; 
} 

function B() { 
    this.val = "bar"; 
    this.say = function() { alert("B: " + this.val); }; 
} 

function test() { alert("T: " + this.val); } 

var a = new A(), b = new B(); 

a.say()   // alerts "A: foo" 
b.say()   // alerts "B: bar" 
b.say.call(a); // alerts "B: foo";  (.call() switches the context) 
test()          // alerts "T: undefined" (val does not exist in window) 
test.call(b)    // alerts "T: bar"  (Ah!) 

あなたが暗黙的にコンテキストを定義しない限り、(b.say()thisbになることを意味する)または明示的に:。thisコンテキスト関数がで呼び出される任意の関数がどのコンテキストで呼び出すことができます維持します)、コンテキストはグローバルコンテキスト(ブラウザではwindowオブジェクト)になります。 Ajaxコールバックの場合もそうです。

+1

なぜそれもうまくいかない理由を説明していただきありがとうございます。 – Lucas

+0

@ルーカスよろしくお願いします。 (これは非常に一般的な誤解です。私は説明コードに加えた小さな追加も参照してください) – Tomalak

0

は、この構文を使用します。

function List() { 
    this.tasks = new Array(); 
} 

List.prototype.add = function(taskItem) { 
    this.tasks.push(taskItem); 
} 

var list = new List(); 
list.add(…); 

また、あなたの受け入れ率を改善しようと、人々はあなたを助けるために、より喜んでます。

3

jQuery Ajaxコールバックのコンテキストは、Ajaxリクエストの作成に使用されるオプションを表すオブジェクトです。つまり、$.ajax(options)への呼び出しに渡されたオプションオブジェクトは$.ajaxSettingsとマージされます。 contextオプションを設定すると、コンテキストを上書きできます。これは$.getJSON()の代わりに$.ajax()を呼び出すことを意味します。

$.ajax({ 
    context: this, 
    url: url, 
    dataType: 'json', 
    success: callback 
}); 
+0

+1うわー、私はこれを知らなかった。とても便利! – Tomalak

+0

私は、入力/知識のおかげで同意します! – Lucas

0

Tomalakさんの答えを踏まえて、 "self"という宣言をメインオブジェクトレベルに移動することができます。これは、ネストされたオブジェクト関数内でこれを使用する場合に非常に有用であることが証明されています。

function List(){ 
    var self = this; 
    self.tasks = new Array(); 
    self.add = function(taskItem){ 
     self.tasks.push(taskItem); 
    }; 
    self.load = function(url){ 
     $.getJSON(
     url, 
     function(data){ 
      $.each(data, function(key,val){ 
       var task = new Task({ 
        id:val.pkTaskId, 
        title:val.fldName, 
        status:val.fldStatus 
       }); 
       self.add(task); 
      }); 
     }); 
    } 
} 

var userList = new List(); 
userList.load(url);