将一个数组转换为树形结构

6

有人能解释一下这段代码吗?我不理解“for”结构内部的内容。

 var tree = {}

function addToTree(tree, array) { 
   for (var i = 0, length = array.length; i < length; i++) {
       tree = tree[array[i]] = tree[array[i]] || {}
   }
}

addToTree(tree, ["a", "b", "c"])
addToTree(tree, ["a", "b", "d"])

/*{
    "a": {
        "b": {
            "c": {},
            "d": {}
        }
    }
}*/

1
这段代码能正常工作吗?如果可以的话,我也想知道发生了什么。 - Jesse Jashinsky
它可以将一个数组转换成一棵树,就像是一个对象树,注释代码是树的输出。这是原始帖子:https://dev59.com/8VDTa4cB1Zd3GeqPIFGi - Luis Palomá
我开始阅读你的代码并写下了答案,但是我得不到你得到的相同答案!在我的看来,当这段代码运行时,tree应该在最后成为空对象。 - Vivian River
2个回答

1

我扩展了for循环的主体,并添加了一些注释,试图使事情更加明确。

for (var i = 0, length = array.length; i < length; i++) {
   // Assign the current item in the array to a variable
   var current = array[i];

   // If there is no property on the "tree" object corresponding to the value of 
   // "current", set this property to a new object
   if (!tree[current]) {
      tree[current] = {};
   }

   // Set the "tree" variable to the field in the "tree" object whose 
   // name corresponds to "current". On the next loop iteration, "tree" will
   // refer to this "child" object, resulting in a tree-like object being
   // created as we iterate.
   tree = tree[current];
}

哦,我现在明白了!起初,我以为我们正在全局范围内重写树的值,但是tree也是函数参数的名称! - Vivian River
2
@DanielAllenLangdon 正确 - 这使得 OP 的帖子变得不必要地混乱,因为 addToTree 作用域内的 tree 的值将绑定到传入的任何内容上,在原始示例中也刚好是称为 tree 的全局变量。 - Donut

1

在函数内部引用tree变量之前,可能会让人感到困惑,因为它会遮盖同名的外部变量。但由于 JavaScript 中引用的工作方式,它最终仍然会修改外部变量。

以下是它的逐步操作,仅考虑第一个调用:

  1. 调用函数并将 tree (即 {}) 和 ["a", "b", "c"] 作为参数
  2. 循环数组。
    1. 检查树中是否已经有了属性名为 "a" 的属性;如果没有,则创建它并赋值为 {}
    2. 现在完整的树看起来像 { a : {} }
    3. 现在我们正在处理的树是 tree.a (为空)
    4. 检查当前树中是否已经有了属性名为 "b" 的属性;如果没有,则创建它并赋值为 {}
    5. 现在完整的树看起来像 { a : { b: {} } }
    6. 现在我们正在处理的树是 tree.a.b (为空)
    7. 检查当前树中是否已经有了属性名为 "c" 的属性;如果没有,则创建它并赋值为 {}
    8. 现在完整的树看起来像 { a : { b: { c: {} } } }
    9. 现在我们正在处理的树是 tree.a.b.c (为空)
  3. 函数结束

谢谢你的帮助,我非常理解。 - Luis Palomá

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接