0

我有一个像这样的对象结构;

{
   this.parent = undefined;
   this.children = [];
}

中的所有值children都具有与上述相同的结构,除了它们的parent将是对将其作为子对象的对象的引用。

如何在孩子的对象上下文中轻松地遍历孩子的所有孩子等?

我知道如何让孩子们为一个对象循环

obj.children.forEach(function(child) {

});

但是,当孩子们可以进入 10-20-30 深层次时,我如何迭代所有孩子的孩子?

4

3 回答 3

5

使用递归

function deepForEach(node, fn) {
    fn(node);
    node.children.forEach(function(child) {
        deepForEach(child, fn);
    });
}

deepForEach(obj, function(obj) {
    console.log(obj);
});

如果我们用简单的英语陈述它,它的工作方式就会变得很明显:

  • 如果没有子节点,只需使用节点调用回调。(基本情况)
  • 如果有孩子,首先处理我们自己,然后为每个孩子做这整个过程。

这种类型的递归称为前序遍历

于 2013-05-19T05:20:04.580 回答
1

我们将编写一个递归函数。递归意味着它将再次执行自己:

function iterate(obj) {
    // we will write the parent and the name
    console.log(obj.parent + ' | ' + obj.name);

    // if it has children
    if (obj.children.length) {
        // for each child
        for (var i = 0, l = obj.children.length; i < l; i++) {
            // we will call this function again
            arguments.callee(obj.children[i]);
        }
    }
}

现在,如果我们有这样的对象:

var obj = {
    name: 'P1',
    parent: undefined,
    children: [
        {
            name: 'P2',
            parent: 'P1',
            children: []
        },
        {
            name: 'P3',
            parent: 'P1',
            children: [
                {
                    name: 'P4',
                    parent: 'P3',
                    children: [
                        {
                            name: 'P5',
                            parent: 'P4',
                            children: []
                        }
                    ]
                }
            ]
        },
        {
            name: 'P6',
            parent: 'P1',
            children: []
        }
    ]
};

我们可以遍历它:

iterate(obj);

FIDDLE DEMO(在浏览器中打开您的控制台)

于 2013-05-19T05:32:18.283 回答
1

标准方法是使用 icktoofay 建议的递归。

在这种处理中更令人讨厌的是如何管理“块”中的遍历(例如,如果您想在使用计时器的 javascript 程序的“背景”中执行此操作)。

在这种情况下,您可以使用显式堆栈:

function process_tree(root_node,
                      process_node,
                      chunk_size,
                      completion_call)
{
    var todo = []; // nodes that need processing

    function processOneChunk() {
        for (var j=0; todo.length && j<chunk_size; j++) {
            var x = todo.pop();
            process_node(x);
            for (var i=0; i<x.children.length; i++) {
                todo.push(x.children[i]);
            }
        }
        if (todo.length) {
            setTimeout(processOneChunk, 0);
        } else {
            completion_call();
        }
    }

    todo.push(root_node);
    setTimeout(processOneChunk, 0);
}
于 2013-05-19T06:44:39.083 回答