2016-07-05 5 views
2

私がJavaScriptで書いた再帰関数に問題がある理由を理解できない。大きなjsonファイルをフィードすると、無限ループに巻き込まれます。 JavaScript閉鎖の仕組みと関係があると感じています。スマートフォンを飛び越えると、自分のコードを見て、何が起こっているのかを説明することができます。JavaScript再帰の奇妙な動作ですか?

私はPHPの関数ラインを移植して、私が期待する出力を生成しています。

のJavaScript:PHPに移植

var jsonfile = process.argv[2]; 

json = require("./"+jsonfile); 

path = "2"; 

buildPaths(json, path); 

function buildPaths(json, path) { 

    if (json.Children == null || json.Children.length == 0) { 

     console.log(path + "/" + json.TypedItemId); 

    } else { 

     for (i = 0; i < json.Children.length; i++) { 
      buildPaths(json.Children[i], path + "/" + json.TypedItemId); 
     } 
    } 

} 

<?php 
$jsonfile = $argv[1]; 
$json = json_decode(file_get_contents($jsonfile)); 

$path = "2"; 

buildPaths($json, $path); 

function buildPaths($json, $path) { 


    if ($json->Children == null || count($json->Children) == 0) { 

     echo $path . "/" . $json->TypedItemId . "\n"; 

    } else { 

     for ($i = 0; $i < count($json->Children); $i++) { 
      buildPaths($json->Children[$i], $path . "/" . $json->TypedItemId); 
     } 
    } 

} 

(サイズの大きいファイルはさらにすごみを引き起こす)でテスト用のサンプルJSONファイル:

{ 
    "TypedItemId": 4, 
    "Children": [ 
    { 
     "TypedItemId": 67, 
     "Children": [ 
     { 
      "TypedItemId": 90, 
      "Children": [ 
      { 
       "TypedItemId": 90, 
       "Children": [ 
       { 
        "TypedItemId": 67, 
        "Children": [ 
        { 
         "TypedItemId": 90, 
         "Children": [ 
         { 
          "TypedItemId": 90, 
          "Children": [] 
         }, 
         { 
          "TypedItemId": 908, 
          "Children": [] 
         } 
         ] 
        }, 
        { 
         "TypedItemId": 908, 
         "Children": [ 
         { 
          "TypedItemId": 90, 
          "Children": [] 
         }, 
         { 
          "TypedItemId": 908, 
          "Children": [] 
         } 
         ] 
        } 
        ] 
       } 
       ] 
      }, 
      { 
       "TypedItemId": 908, 
       "Children": [] 
      } 
      ] 
     }, 
     { 
      "TypedItemId": 908, 
      "Children": [ 
      { 
       "TypedItemId": 90, 
       "Children": [] 
      }, 
      { 
       "TypedItemId": 908, 
       "Children": [] 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 

PHP出力(正しいです):

2/4/67/90/90/67/90/90 
2/4/67/90/90/67/90/908 
2/4/67/90/90/67/908/90 
2/4/67/90/90/67/908/908 
2/4/67/90/908 
2/4/67/908/90 
2/4/67/908/908 

JavaScriptのノード出力(間違った):

for (i = 0; i < json.Children.length; i++) { 

代わりのvarを使用して、ローカル変数を宣言:あなたのループ内で使用しているイテレータを除き、あなたのJavaScriptと間違っ

2/4/67/90/90/67/90/90 
2/4/67/90/90/67/90/908 
+0

、あなたのJSコード内の任意のクロージャを持っていません。ただの正常な機能です。 –

+0

ok ty 何が起こっているのか不思議で、出力が異なっています。私が見ている結果を引き起こしていることを私が理解していないJavaScriptに関して何か疑問に思っています。 –

答えて

4

がNothing、グローバルオブジェクトのプロパティiをイテレータとして使用しています。これは、すべての呼び出しがbuildPathsの間で共有されています。

代わりにローカル変数を使用します。

for (var i = 0; i < json.Children.length; i++) { 

はそれを自分で試してみてください。

var json = {"TypedItemId":4,"Children":[{"TypedItemId":67,"Children":[{"TypedItemId":90,"Children":[{"TypedItemId":90,"Children":[{"TypedItemId":67,"Children":[{"TypedItemId":90,"Children":[{"TypedItemId":90,"Children":[]},{"TypedItemId":908,"Children":[]}]},{"TypedItemId":908,"Children":[{"TypedItemId":90,"Children":[]},{"TypedItemId":908,"Children":[]}]}]}]},{"TypedItemId":908,"Children":[]}]},{"TypedItemId":908,"Children":[{"TypedItemId":90,"Children":[]},{"TypedItemId":908,"Children":[]}]}]}]}; 
 

 
var path = "2"; 
 

 
buildPaths(json, path); 
 

 
function buildPaths(json, path) { 
 
    if (json.Children == null || json.Children.length == 0) { 
 
     console.log(path + "/" + json.TypedItemId); 
 
    } else { 
 
     for (var i = 0; i < json.Children.length; i++) { 
 
      buildPaths(json.Children[i], path + "/" + json.TypedItemId); 
 
     } 
 
    } 
 
}

+0

は華麗です!私はグローバル変数LOLでした。今すぐテストしてください。 Ty =) –

+1

これらのタイプのミスを簡単にキャッチするには、厳密なモードを 'use strict'で有効にしてください。 –

+0

そうでした!コードレビューの目をしてくれてありがとう。 –

関連する問題