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 に答える