【问题标题】:Recursive JavaScript Method Scope递归 JavaScript 方法范围
【发布时间】:2013-02-27 21:04:11
【问题描述】:

我有这个递归函数,它假设通过一个 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);
            });
        }
    });
}

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

最终,我想返回一个子 group.id 的数组。我不知道怎么去那里......

【问题讨论】:

  • 如何检测subgroupids 已被完全填满?为此,您需要某种回调。
  • 你是对的,Bergi。查看我的编辑。

标签: javascript recursion


【解决方案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

【讨论】:

    【解决方案2】:

    内部的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】:

      这是因为 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);
                  });
              }
          });
      }
      

      【讨论】:

        【解决方案4】:

        您的this 与以前的this 不同。也许在您第一次调用getSubGroups 之前,将this 保存到与它所引用的对象更相关的变量名中(我将使用someObject...),然后再调用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"了解更多详情。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-15
          • 2016-06-25
          • 1970-01-01
          • 2016-06-23
          • 2017-07-29
          • 2016-07-11
          相关资源
          最近更新 更多