在多个对象的上下文中调用相同的函数?

时间:2013-05-19 05:17:13

标签: javascript object foreach

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

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

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

如何轻松地迭代所有孩子的孩子等,但是在孩子的对象环境中呢?

我知道如何为一个物体循环孩子

obj.children.forEach(function(child) {

});

但是,如果孩子们可以进入10-20-30深的heirachy,我怎么能迭代所有孩子的孩子?

3 个答案:

答案 0 :(得分:5)

使用recursion

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

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

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

  • 如果没有子节点,只需使用节点调用回调。 (基本情况)
  • 如果有孩子,先与自己打交道,然后为每个孩子做一整个程序。

这种类型的递归称为preorder traversal

答案 1 :(得分: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 (在浏览器中打开您的控制台)

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