I'm trying to create an object called List. This object has a method add which simply pushes a task object onto this tasks array. I also built a load method to load items from a url.
My issue is I can't seem to reference the add method from within the load method, I get the following error:
Uncaught TypeError: Object # has no method 'add'.
How do I reference the add method from within the load method? The code I am using is below.
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)
Try this:
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);
});
}
);
}
}
The issue is that this
is not what you think it is in the Ajax callback. The callback function is not called in the object's context, it is called in the global context (so this
will point to the window
object).
Saving an object reference (by convention called self
) beforehand is necessary.
this
will not always point to the object instance a function "belongs to". In fact, a function does not belong to an object in the same way it does in other languages. this
maintains the context a function is called in. Any function can be called in any context:
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!)
Unless you define context implicitly (b.say()
implies that this
will be b
) or explicitly (by using call()
or apply()
), the context will be the global context - which in a browser is the window
object. And that's exactly the case for your Ajax callback.