2013-07-19 51 views
4

我正在处理一个项目,该项目有一个疯狂的for循环来展开D3.js画布交互式中的节点。基本上,我想要的是扩大所有的孩子。所以如果一个物体有一个孩子,我想扩大它们。For循环在对象上失控

我从这里删去了一大块代码。有太多的循环是荒谬的。我怎样才能减少到一个简单的“找到所有的孩子,preform切换();和更新();”?

$('.expandAll').click(function(e) { 
    e.preventDefault(); 
    length = root.children.length; 

    for (var i = 0; i < length; i++) { 
     toggle(root.children[i]); 
     update(root); 

     if (root.children[i]['children']) { 
      childlength = root.children[i]['children'].length; 

      for (var j = 0; j < childlength; j++) { 
       toggle(root.children[i]['children'][j]); 
       update(root); 

       if (root.children[i]['children'][j]['children']) { 
        childlength2 = root.children[i]['children'][j]['children'].length; 

        for (var k = 0; k < childlength2; k++) { 
         toggle(root.children[i]['children'][j]['children'][k]); 
         update(root); 
        } 
       } 
      } 
     } 
    } 
}); 
+2

这......这是失控了!停止主反应堆! ......但真的。为什么不只是建立一些功能? – jdero

+3

递归!递归!递归! –

+0

你知道吗,递归函数是什么? 是否递归 –

回答

3

听起来像是一个很好的例子递归:

$('.expandAll').click(function(e) { 
    e.preventDefault(); 

    expandAll(root); 
}); 

var expandAll = function (node) { 
    toggle(node); 
    update(node); 

    // edit: if nodes with no children are lacking the children property 
    if (!node.children) { 
     return; 
    } 

    for (var i = 0, length = node.children.length; i < length; i++) { 
     expandAll(node.children[i]); 
    } 
}; 

我不知道什么toggleupdate究竟意味着什么,但你可以后执行只是一个单一的顶级update通话呼叫expandAll(root);

+0

这将导致堆栈溢出或'无法访问'我'未定义的异常?看起来叶节点确实有* no * children数组而不是一个长度为0. – Bergi

+0

@Bergi听起来像是节点对象的问题,而不是循环:) – jbabey

+0

是的,我刚刚得到“无法读取长度的属性” 。 – dallen

0

使用recursion!如果您只需要支持三个级别,则可以为此引入一个计数器变量。

$('.expandAll').click(function(e) { 
    e.preventDefault(); 
    expandAll(root, root.children/*, 3*/); 
} 
function expandAll(root, children/*, lev*/) { 
    if (!children/* || lev<=0 */) return; 
    var length = children.length; 
    for (var i = 0; i < length; i++) { 
     toggle(children[i]); 
     update(root); 
     expandAll(root, children[i].children/*, lev-1*/); 
    } 
} 

顺便说一句,你确定,你需要每一个toggle后呼吁rootupdate?当所有的孩子都被切换时,最后一次称呼它会更有意义。

0

不知道这是否会帮助,但东西我已经和嵌套对象做:

object = { 
    children: [], // array of similar objects with children property and update function 
    update: function(data){ 
     // update this item 
     this.data = data; 

     // update each immediate child 
     if (this.children) 
      for (var i in this.children) 
       this.children[i].update(data); 
    } 
}; 

// then you just call update on the first item: 
object.update(data); 

如果按照这种模式,而不是在根级别设置复杂的循环,你只需遍历直接的孩子,并呼吁他们的更新功能,然后循环通过他们的孩子,并一路下降。

我不是一个伟大的JS开发者,只是我在做什么,因为我是用一天工作的一些嵌套的注释;)