JavaScript递归奇怪的行为?

时间:2016-07-05 20:02:12

标签: javascript php node.js recursion closures

我无法理解为什么我在JavaScript中编写的递归函数存在问题。当我为它提供一个大的json文件时,它会被无限循环捕获。我觉得它与JavaScript闭包的工作方式有关。跳出一个聪明的人可以查看我的代码并解释发生了什么。

我已经将行的函数行移植到PHP,它产生了我期望的输出。

JavaScript的:

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:

<?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节点输出(不正确):

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

1 个答案:

答案 0 :(得分:4)

您的JavaScript没有任何问题,除了您在循环中使用的迭代器:

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

不是使用var声明局部变量,而是使用全局对象上的属性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);
        }
    }
}

相关问题