第一次通过后返回的递归JavaScript

第一次通过后返回的递归JavaScript,javascript,recursion,marionette,Javascript,Recursion,Marionette,我有以下递归javascript函数,该函数在backbone.marionete CollectionView的子级上循环,它的子级ItemViews依次是CollectionView: findViewByCid: function(cid, children){ var col = (arguments.length === 1) ? this.children : children; if(cid in col){ return col[ci

我有以下递归javascript函数,该函数在backbone.marionete CollectionView的子级上循环,它的子级ItemViews依次是CollectionView:

  findViewByCid: function(cid, children){
      var col = (arguments.length === 1) ? this.children : children;

      if(cid in col){
        return col[cid];
      }

      for(child in col){
        var grandChildren = col[child].children;

        if(cid in grandChildren){
          return grandChildren[cid];
        }

        if(grandChildren && (!jQuery.isEmptyObject(grandChildren))){
          return this.findViewByCid(cid, grandChildren);
        }
      }
    }
我这样称呼它:

var view=DocumentManager.Documents.treeRoot.findViewByCid(model.cid)

问题在于线路:

return this.findViewByCid(cid, grandChildren);
如果我有这样的层次结构

c1
|_c2
  |_c3
|_c4
  |_c5
然后te return语句将导致函数在通过th3 c2节点后退出,并且永远不会到达c4等

如果删除return语句,则会找到正确的子级,但返回null


如何继续解析层次结构并返回值?

返回将退出函数

尝试将所有内容保存在一个var中,并在最末尾返回,如果需要返回多个值,则可以使用数组。 (不要在for循环中声明变量!)

这里有一个建议

findViewByCid: function(cid, children){
  var willBeReturned=[];
  var grandChildren;

  var col = (arguments.length === 1) ? this.children : children;

  if(cid in col){
    willBeReturned[willBeReturned.length] = col[cid];
  }
  for(child in col){
    grandChildren = col[child].children;

    if(cid in grandChildren){
      willBeReturned[willBeReturned.length] = grandChildren[cid];
    }

    if(grandChildren && (!jQuery.isEmptyObject(grandChildren))){
      willBeReturned[willBeReturned.length] = this.findViewByCid(cid, grandChildren);
    }
  }
  return willBeReturned;
}
我相信行if(cid in col)不符合您的要求。试一试

findViewByCid: function(cid, children){
  if (this.cid === cid) return this;

  var col = (arguments.length === 1) ? this.children : children;
  for(var childI in col){
    var child = col[childI];

    if (child.cid === cid) {
      return child;
    }

    var grandChildren = child.children;
    if(grandChildren && (!jQuery.isEmptyObject(grandChildren))){
      return this.findViewByCid(cid, grandChildren);
    }
  }
}

只有在找到某个对象时才需要返回,否则
return
语句将在没有搜索其他子对象的情况下中断循环。这是一个简单的你想要的

假设函数位于每个子节点的原型上(不仅在根节点上):

或具有将节点作为参数的函数:

function findViewByCid(cid, node) {
    var col = node.children;
    if (!col)
        return false;
    if (cid in col)
        return col[cid];
    for (var child in col) {
        var found = findViewByCid(cid, col[child]);
        if (found)
            return found;
    }
    return false;
}
但是,该算法似乎无法找到根节点。如果您可以通过
cid
识别当前节点,而不是查看其所有子节点,则会更好:

if (this /*… is what we have searched for */)
    return this;
首先,它看起来像Backbone.js,如果它是,标记它可能会有所帮助。我觉得人们可能会遇到类似的问题,并且知道更好的方法来存储对视图的引用

你只想在找到东西的时候还它。。。仅在第一次递归调用中使用return将强制该方法在搜索第一组子对象时停止执行,即使没有找到任何内容


我还想在for循环中引入的新变量前面添加一个var,如果没有它,该变量将是全局变量。

这就是我最后得到的,它是backbone.marionete,使用collectionView的itemView迭代collectionView:

findViewByCid: function(cid){
  var self = this,
      ret;

  function findView(cid, children){
    var col = (arguments.length === 1) ? self.children : children,
    grandChildren;

    if(cid in col){
      ret = col[cid];
    }

    for(child in col){
      grandChildren = col[child].children;

      if(cid in grandChildren){
        ret = grandChildren[cid];
      }

      if(grandChildren && (!jQuery.isEmptyObject(grandChildren))){
        findView(cid, grandChildren);
      }
    }
  };

  findView(cid);

  return ret;
}

很难解释。考虑CID为5。模型中的cid检查是否存在与模型['cid']==5或model.cid==5不同的模型[5]。它是backbone.marionette,我正在使用一个项目视图迭代CollectionView,该项目视图是CollectionView,这使得它比通常情况下更复杂。
findViewByCid: function(cid, children) {
    var col = (arguments.length === 1) ? this.children : children;

    if(cid in col){
        return col[cid];
    }       
    for(var childKey in col) {
        var grandChildren = col[childKey].children,
            childView;

        if (grandChildren) {
            childView = this.findViewByCid(cid, grandChildren);
        }

        if (childView) {
            return childView;
        }
    }
    return null;
}
findViewByCid: function(cid){
  var self = this,
      ret;

  function findView(cid, children){
    var col = (arguments.length === 1) ? self.children : children,
    grandChildren;

    if(cid in col){
      ret = col[cid];
    }

    for(child in col){
      grandChildren = col[child].children;

      if(cid in grandChildren){
        ret = grandChildren[cid];
      }

      if(grandChildren && (!jQuery.isEmptyObject(grandChildren))){
        findView(cid, grandChildren);
      }
    }
  };

  findView(cid);

  return ret;
}