1

所以我有一个看起来像这样的代码块:

  stack.forEach(function(element){
    //sys.puts(sys.inspect(element, false, null));
    console.log('-----element start-----');
    console.log(element.type + ':' + element.raw);
    console.log('-----element end-----');

    if(element.children){
      element.children.forEach(function(childElement){
        stack.push(childElement);
      });
    }
  });

问题是这不像我想的那样,除了一个堆栈来表现,并想知道这是否与 JavaScript 本身有关。我看到的问题是,当我为每个孩子调用 stack.push 以将其添加到堆栈中进行处理时,初始 stack.forEach() 似乎没有拾取它,它只记录到顶级元素. 如果我尝试在此之后直接执行另一个 stack.forEach() ,则它会显示下一级子元素,因此我知道 .push 正在将子元素添加到堆栈中。

似乎 .forEach() 按原样抓取数据,如果它们发生在 foreach 中,则不会获得更新。JavaScript 是这样吗?有没有不同的方法可以完成同样的事情(能够处理顶级元素和它下面的所有级别的子元素)?

4

2 回答 2

3

你的假设是正确的。ForEach 函数获取数组的快照,并且不会处理任何更新。

您正在尝试实现一个经典的树遍历算法,该算法最容易编码为递归函数,如下所示:

  var stack = [];

  function traverse (element) {
    //sys.puts (sys.inspect(element, false, null));
    console.log ('-----element start-----');
    console.log (element.type + ':' + element.raw);
    console.log ('-----element end-----');

    stack.push (element);  // for preorder traversal (parent before children)

    if (element.children)
      element.children.forEach (traverse);

    // stack.push (element);  // for postorder traversal (children before parent)
  };

  traverse (document.body);  // for example
于 2012-10-24T13:26:03.013 回答
1

是的,.forEach仅迭代数组最初具有的范围,它与.length值的副本一起使用。如果你想改变这种行为,我推荐一个经典的循环,length每次都查询属性:

var stack = […];
for (var i=0; i<stack.length; i++) {
    // process stack[i]
    stack.push(…);
}

甚至更类似于列表的行为

var stack = […];
while (stack.length) {
    var cur = stack.shift();
    // process cur
    stack.push(…); // with variable arguments, you want to stop somewhen :-)
}

如果您不想/不需要自己维护堆栈,则递归函数是树遍历的正确选择。

于 2012-10-24T17:22:41.047 回答