JavaScript递归奇怪的行为?
Posted
技术标签:
【中文标题】JavaScript递归奇怪的行为?【英文标题】:JavaScript recursion odd behaviour? 【发布时间】:2016-11-07 18:47:00 【问题描述】:我无法理解为什么我用 javascript 编写的递归函数会出现问题。当我给它提供一个大的 json 文件时,它会陷入无限循环。我觉得这与 JavaScript 闭包的工作方式有关。跳个聪明的可以看看我的代码并解释发生了什么。
我已将 line 的函数 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 节点输出(不正确):
2/4/67/90/90/67/90/90
2/4/67/90/90/67/90/908
【问题讨论】:
您的 JS 代码中没有任何闭包。只是一个正常的功能。 好吧,你仍然对导致不同输出的原因感到好奇。我想知道我不理解的 JavaScript 是什么导致了我看到的结果 【参考方案1】:除了您在循环中使用的迭代器之外,您的 JavaScript 没有任何问题:
for (i = 0; i < json.Children.length; i++)
您使用全局对象上的属性i
作为迭代器,而不是使用var
声明局部变量,它在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);
【讨论】:
太棒了!! i 是一个全局变量 LOL。现在测试它。 Ty =) 要轻松发现这些类型的错误,请确保使用use strict
启用严格模式。
是的,做到了!感谢您成为我的代码审查眼睛。
"use strict";
会救你的
谢谢大家,两个重要的教训。 “使用严格”;获取更多错误消息,并始终声明所有变量。曾经看过一个演讲,建议在编写 JavaScript 时以 C 风格在函数顶部声明变量,以免自己头疼。我完全倾听并接受了它,就像是的,是的。但是,除非你自己动手,否则你永远不会真正学习 =)以上是关于JavaScript递归奇怪的行为?的主要内容,如果未能解决你的问题,请参考以下文章