递归JavaScript方法范围

时间:2013-02-27 21:04:11

标签: javascript recursion

我有这个递归函数,假设要通过JSON对象来查找所有子组。这就是我所拥有的:

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

...其中getGroups是一个返回所有组的异步函数。

我的问题是当它进入递归调用时,我得到的错误是:

Uncaught TypeError: Object #<Object> has no method 'getSubGroups' 

我猜这是一个范围问题,但我无法弄清楚它有什么问题。有什么想法吗?

修改

正如Bergi指出的那样,我需要回调。这就是我现在所拥有的:

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

现在的麻烦是当我调用回调时,它说函数是未定义的。

最终,我想返回一个sub group.id的数组。我不确定如何到达那里......

4 个答案:

答案 0 :(得分:1)

这是因为each中定义的内部函数不属于类/对象的this实例,而不是它指的是回调函数本身。为了绕过这个问题,在对象构造函数中,我将下面的内容:

一般解决方案:

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
     }

}

修复您的代码:

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

答案 1 :(得分:1)

您的this与以前this不一样。在您第一次this来电之前,可能会将someObject保存到与其引用的对象更相关的变量名称中(我将使用getSubGroups ...),然后调用someObject.getSubGroups后面。

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

发生这种情况的原因是因为您的函数是从$.each实现调用的。我会参考MDN docs of "this"了解更多详情。

答案 2 :(得分:1)

内部this指的是$.each回调,你可以这样做:

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 :(得分:1)

这是因为this是在函数级别定义的,并且在这种情况下绑定到您为内部函数迭代的数组中的项目。内部函数中的this与外部函数中的this不同。你可以通过设置解决这个问题 外层var that = this;,并在内部函数

中引用that
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);
            });
        }
    });
}

有关详情,请参阅How do closures work

此处为How this works in JS