像JavaScript / Node一样创build一个类似Stack的行为

所以我有一个如下所示的代码块:

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); }); } }); 

问题是,这不是像我会performance得像一个堆栈行为,并想知道如果这在JavaScript本身的问题。 我看到的问题,如果当我调用stack.push为每个孩子将其添加到堆栈进行处理,初始stack.forEach()似乎并没有拿起它,它只是logging到顶层的元素。 如果我试图在这个之后直接执行另一个stack.forEach(),它会显示下一级子元素,所以我知道.push很不情愿地将子元素添加到堆栈中。

它几乎可以像.forEach()那样抓取数据,如果它们在foreach中发生,就不会得到更新。 这对于JavaScript是否正确? 有什么不同的方式可以完成同样的事情(能够处理顶层元素和其下的所有层次的子元素)?

你的猜想是正确的。 ForEach函数获取数组的快照,任何更新都不会被处理。

您正试图实现一个经典的树遍历algorithm,它可以很容易地编码为recursion函数,如下所示:

  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 

是的, .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 :-) } 

如果你不想/自己维护堆栈,recursion函数是树遍历的正确select。