2012-01-28 95 views
1

我在創建一個名爲List的對象。該對象有一個方法添加,它只是將任務對象推送到這個任務數組上。我還構建了一個加載方法來加載url中的項目。Javascript對象方法問題

我的問題是我似乎無法從負載方法中,我得到以下錯誤引用add方法:

遺漏的類型錯誤:對象#有沒有方法「添加」。

如何從加載方法中引用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回調。回調函數不在對象的上下文中調用,它在全局上下文中調用(因此this將指向window對象)。

需要事先保存對象引用(通過約定稱爲self)。


this不會總是指向對象實例的函數「屬於」。實際上,函數不像其他語言中那樣屬於一個對象。 this保持背景調用函數中的任何函數可以調用在任何情況下:

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)或明確(通過使用call()apply() ),上下文將是全局上下文 - 在瀏覽器中是window對象。 Ajax回調就是這種情況。

+1

謝謝你解釋爲什麼它不能正常工作。 – Lucas 2012-01-28 20:19:33

+0

@Lucas不客氣。 (這是一個非常常見的誤解,另請參閱我對解釋代碼的小補充。) – Tomalak 2012-01-28 20:31:18

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選項來覆蓋上下文。這意味着撥打$.ajax()而不是$.getJSON()

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

+1哇,我不知道這一點。很方便! – Tomalak 2012-01-28 19:35:04

+0

我同意,感謝您的輸入/知識! – Lucas 2012-01-29 00:05:32

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);