问题
I have this recursive function that is suppose to go through a JSON object to find all the subgroups. Here is what I have:
var subgroupIds = [];
this.getSubGroups = function (groupId) {
this.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return subgroupIds;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
this.getSubGroups(group.id);
});
}
});
}
...where getGroups is an asynchronous function that returns all the groups.
My problem is when it gets to the recursive call, I get the error that says:
Uncaught TypeError: Object #<Object> has no method 'getSubGroups'
I'm guessing it's a scope issue but I can't figure out what's wrong with it. Any ideas?
EDIT:
As Bergi pointed out, I need to have a callback. This is what I have now:
var subgroupIds = [];
var that = this;
this.getSubGroups = function (groupId,callback) {
this.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
callback(group.id);
that.getSubGroups(group.id);
});
}
});
}
The trouble now is when I call the callback, it says the function is undefined.
Ultimately, I want to return an array of sub group.id's. I'm not sure how to get there...
回答1:
This is because this is defined at a function level, and is bound to the item in the array you're iterating over for the inner function in this case. this within the inner function does not refer to the same thing as this within the outer function. You can get around this by setting
var that = this; on the outer level and referencing that from within the inner function
var subgroupIds = [];
var that = this;
this.getSubGroups = function (groupId) {
this.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return subgroupIds;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
that.getSubGroups(group.id);
});
}
});
}
For more see How do closures work
And here for How this works in JS
回答2:
The inner this refers to $.each callback, you can do something like this:
var subgroupIds = [];
var self = this;
self.getSubGroups = function (groupId) {
self.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return subgroupIds;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
self.getSubGroups(group.id);
});
}
});
}
回答3:
This is because thi inner function, defined in each does not belong to this instance of your class/object, isntead it refers to the callback function itself. To bypass this problem, at the object constructor, I put the folowing:
Solution in general:
function SimpleClass() {
var _this = this; //Private property, will be shared in all functions defined in the class
this.value = "Hello";
this.value2 = " world!";
function say() { //private function - use _this (this means something else here)
return _this.say; //Gets property of the object
}
this.say = function() { //Public function - use this
alert(this.value+say()); //Here, we can use both this and _this
}
}
Fix for your code:
var _this = this;
var subgroupIds = [];
this.getSubGroups = function (groupId) {
this.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return subgroupIds;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
_this.getSubGroups(group.id);
});
}
});
}
回答4:
Your this is not the same this as before. Perhaps save this into a variable name more relevant to the object it's referencing (I'll use someObject...) before your first getSubGroups call, and then call someObject.getSubGroups later.
var subgroupIds = [];
var someObject = this;
someObject.getSubGroups = function (groupId) {
this.getGroups("groupId="+groupId, function(groups) {
if ($.isEmptyObject(groups)) {
return subgroupIds;
} else {
$.each(groups, function(index,group) {
subgroupIds.push(group.id);
someObject.getSubGroups(group.id);
});
}
});
}
The reason why this happens is because your function is called from the $.each implementation. I would refer to MDN docs of "this" for more details.
来源:https://stackoverflow.com/questions/15122378/recursive-javascript-method-scope