2012-01-28 96 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);