对于对象的循环失控

时间:2013-07-19 15:24:28

标签: javascript jquery for-loop

我正在使用一个具有这个疯狂for循环的项目来扩展D3.js画布交互中的节点。基本上,我想要的是扩大所有孩子。因此,如果一个对象有一个孩子,我想扩展它们。

我从中删除了一大块代码。循环太多了,这太荒谬了。我怎样才能将其简化为一个简单的"找到所有的孩子,preform toggle();和update();"?

$('.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);
                    }
                }
            }
        }
    }
});

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);调用。

答案 1 :(得分: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*/);
    }
}

顺便说一下,您确定需要在每个update之后致电root上的toggle吗?当所有孩子都被切换时,最终称它为一次会更有意义。

答案 2 :(得分: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开发人员,只是我正在做的一些我前几天工作的嵌套评论;)