我有以下递归javascript函数,它循环遍历backbone.marionette CollectionView的子节点,它们具有子集ItemViews依次为CollectionViews:
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。
如何继续解析层次结构并返回值?
答案 0 :(得分:0)
返回会退出您的功能。
尝试将所有内容保存在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;
}
答案 1 :(得分:0)
只有在找到某些内容时才需要返回,否则return
语句将在不搜索其他子项的情况下中断循环。这是一个简单的depth-first-search你想要的东西。
假设函数在每个子节点的原型上(不仅在根节点上):
findViewByCid: function(cid) {
var col = this.children;
if (!col) // break if the node has no children
return false;
if (cid in col) // look for cid and return the node if one found
return col[cid];
for (var child in col) {
// search through each child and return the result if something is found
var found = col[child].findViewByCid(cid);
if (found)
return found;
}
// else nothing was found
return false;
}
或者以节点作为参数的函数:
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;
答案 2 :(得分:0)
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;
}
首先,这看起来像Backbone.js,标记它可能会有所帮助。我觉得人们可能会遇到类似的问题,并且知道更好的方法来存储对视图的引用。
如果找到它,你只想返回一些东西......只要在第一次递归调用时使用return就会强制该方法在搜索第一组孙子时停止执行,即使没有找到任何东西。
我还要在你的for循环中引入的新变量前加一个var - 没有它,变量将是全局变量。
答案 3 :(得分:0)
这是我最终得到的,它是backbone.marionette,使用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;
}
答案 4 :(得分:-1)
我相信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);
}
}
}