JavaScript 递归奇怪的行为?

标签 javascript php node.js recursion closures

我无法理解为什么我用 JavaScript 编写的递归函数出现问题。当我向它提供一个大的 json 文件时,它陷入了无限循环。我有一种感觉,这与 JavaScript 闭包的工作方式有关。希望聪明的人可以查看我的代码并解释发生了什么。

我已将 line for line 函数移植到 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 Node 输出(不正确):

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

最佳答案

除了您在循环中使用的迭代器之外,您的 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);
        }
    }
}

关于JavaScript 递归奇怪的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38211767/

相关文章:

php - 下拉自动填写表格,包括复选框

php - 只选择一个单选按钮

node.js - 如何使用 npx 从包运行 cli 命令而不进行全局安装

javascript - 监听来自服务器、Chrome 扩展程序的事件

javascript - 移动网页中文件的最大大小

php - 使用 Geonames.org 下载的反向地理编码使用什么算法?

javascript - Restify 返回 undefined is not a function in error object

javascript - 错误 Node TypeError : Cannot read property 'req' of undefined at send

javascript - Mootools 未定义

javascript - 我应该如何使用 angularjs 取消选择 html 页面中已选择的复选框?