对一段 js 的树结构中通过子节点查找它所有父节点的代码感到不解,望路过大佬能帮忙解答一下,谢谢

新手上路,请多包涵

前端小白一枚,有一段 js 在树结构中通过子节点去查找它所有的父节点的代码片段,看到有不解的地方,百思不得其解,希望有大佬能路过帮忙解答一下,代码如下:

var data2= [{
    id: 1,
    label: '一级 1',
    children: [{
        id: 4,
        label: '二级 1-1',
        children: [{
            id: 10,
            label: '三级 1-1-2',
            children: [{
                id: 20,
                label: '四级 1-1-2-1'
            }]
        }]
    }]
}];
function getParentId(list,id) {
    for (let i in list) {
        if(list[i].id === id){
            return [list[i]];
           }
        if(list[i].children){
            let node = getParentId(list[i].children, id);
            console.log(node);
            if(node !== undefined){
                return node.concat(list[i]);
            }
        }
    }        
}
getParentId(data2, 20);

打印结果:
image.png

疑问:
在 node 为 [20] 时,会走到它下面的判断中,最后通过 concat 能得到 [20, 10],但是不明白 4 和 1 是什么时候拿到的,而且都已经在 node !== undefined 的判断语句中将代码 return 了,它又是在什么时候进入的循环呢?

阅读 2.9k
2 个回答
function getParentId(list,id) {
    for (let i in list) { // 遍历数组
        if(list[i].id === id){ // 如果数组中的当前行的id与指定id一致,返回这个行
            return [list[i]];
        }
        if(list[i].children){ // 这里用else if你更容易懂。在当前行的id与指定id不一致时,如果该行有children属性,那么
            let node = getParentId(list[i].children, id); // 在该行的children中检查是否有id一致的行,node可能是一行,也可能是undefined
            if(node !== undefined){ // node不是undefined,所以该行的children中有指定id的行
                return node.concat(list[i]);
            }
        }
    }  
    // 这里什么也没写,也就是相当于return undefined.      
}

整体的执行顺序其实是
在data2[0]中查找id=20,没有
-> 尝试查找data2[0].children
-> 在data2[0].children中查找id=20,没有
->-> 尝试在data2[0].children[0].children中查找id=20
->-> 在data2[0].children[0].children中查找id=20,没有
->->-> 尝试在data2[0].children[0].children[0].children中查找id=20
->->-> 在data2[0].children[0].children[0].children中找到了id=20,返回行
->-> 尝试成功,拼接,返回行
-> 尝试成功,拼接,返回行
查找成功,拼接,返回行

实在不明白就看一下递归的基本知识吧。

他不是直接进入到20这个节点去判断的,他是先进入到1这个节点,然后还没结束,就进入到4这个节点,然后又没结束,又进入到10这个节点,最后进入到20这个节点。

20这里命中,开始返回[20]到10这个节点,命中node!==undefind,进行concat,返回[20, 10]到4这个节点,,命中node!==undefind,进行concat,返回[20, 10, 4]到1这个节点,命中node!==undefind,进行concat,返回[20, 10, 4, 1],这才结束。

这也是递归调用的一个隐患所在,如果层级较多,父级得不到释放,就会发生爆栈

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题