我可以在 $.getJSON 函数中使用递归 JavaScript 函数吗?
Posted
技术标签:
【中文标题】我可以在 $.getJSON 函数中使用递归 JavaScript 函数吗?【英文标题】:Can I have a recursive JavaScript function inside a $.getJSON function? 【发布时间】:2015-12-30 16:47:00 【问题描述】:我有一个深度可变的 JSON 文档。一个例子:
[
"type": "firsttype",
"text":
"id": "content"
]
我想做的是检索某些键的值,比如text
。由于我不知道这些键可能出现在 .JSON 中的什么位置,因此我需要使用递归函数。然后我尝试在 html 文件中显示这些键和值。
我这里有一个初步的尝试:
$.getJSON("file.json", function getText (oValue, sKey)
links = [];
if (typeof oValue == "object" || typeof oValue == "array")
for (i in oValue)
getText (oValue [i], i);
else
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
$( "<ul/>",
"class": "my-new-list",
html: links.join( "" )
).appendTo( "body" );
);
当我在本地或远程或python -m SimpleHTTPServer
上加载页面时,我没有收到任何错误,页面上也没有任何内容。我究竟做错了什么?我已将所有 JS 包含在 $.getJSON
调用中,因此不会出现异步问题。
将来我还想包含一个正则表达式检查,以便我可以提取具有特定字符串的值,例如/http/
。最好的方法是什么?
【问题讨论】:
您能否为我们复制此 JSON 的完整结构? 添加错误处理程序....可能是解析错误或请求失败。我们无法知道,但您需要隔离问题。还要检查浏览器开发工具网络中的实际请求以获取线索 @Pointy 我认为如果appendTo
jquery 的东西在某种程度上超出了getText
函数并且不是每次都被调用,那么将links
作为一个全局变量会很有意义。
@AbbasMashayekh,appendTo
jquery 的东西应该在getText
之外并且只调用一次。
【参考方案1】:
我认为您的错误在于变量链接的声明: 它必须在我认为的递归函数之外。 在函数内部每次都会重新初始化。
var links = [];
$.getJSON("file.json", function getText (oValue, sKey)
if (typeof oValue == "object" || typeof oValue == "array")
for (i in oValue)
getText (oValue [i], i);
else
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
$( "<ul/>",
"class": "my-new-list",
html: links.join( "" )
).appendTo( "body" );
);
【讨论】:
【参考方案2】:尝试将您的函数定义移到事件处理程序之外:
function getText (links, oValue, sKey)
if (typeof oValue == "object" || typeof oValue == "array")
for (i in oValue)
getText (links, oValue [i], i);
else
if(oValue && sKey)
links.push ( "<li id='" + oValue + "'>" + sKey + "</li>" );
$( "<ul/>",
"class": "my-new-list",
html: links.join( "" )
).appendTo( "body" );
;
$.getJSON("file.json", function(data, success)
var links = [];
getText (links, data, 0);
);
如有错误,请随时编辑。
目的是将链接数组传递给递归函数,并避免将命名函数定义与 getJSON 混合,至少为了清楚起见,并确保您可以传递初始化的 sKey。
【讨论】:
【参考方案3】:你可以,但在你的情况下你可能不应该
您可以将命名函数作为回调函数传递——这对递归很有用(参见:Using Named Callback Functions In javascript Methods,Ben Nadel)——但在你的情况下,你可能不应该。
根据您的示例,在调用递归函数之前和之后,您需要做一些事情。这些事情,例如声明变量和将元素附加到主体,将需要在递归之外发生[一次]。
因此,传递一个匿名函数作为您的回调,其中包含您的递归函数定义并根据需要调用它。
在您的情况下,您需要为 JSON 响应数组中返回的每个对象调用它。因此,您也可以将其放在迭代器中。这里为了方便我使用了jQuery的$.each()
。
/* FUNCTION THAT MAKES JSON REQUEST */
function doJsonThing()
/* BEGIN REWRITE OF OP's EXAMPLE CODE */
$.getJSON('file.json', function (json)
var links = [];
function getText (key, val)
if (typeof val === 'object' || typeof val === 'array')
for (i in val)
getText(i, val[i]);
else
links.push('<li id="' + val + '">' + key + ' (' + val + ')</li>' );
$.each(json, function (key, val)
getText(key, val);
);
$('<ul/>',
"class": "my-new-list",
"html" : links.join('')
).appendTo('body');
);
/* END REWRITE OF EXAMPLE CODE */
/* THE FOLLOWING IS NOT PART OF THE EXAMPLE,
// IT IS JUST USED TO SIMULATE A SERVER RESPONSE */
/* BEGIN UNIT TEST */
// CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
function json_response(response)
return function (url, success)
success(response);
;
// OVERRIDE $.getJSON WITH DUMMY FUNCTION AND FAKE RESPONSE
$.getJSON = json_response(
// SIMULATED CONTENTS OF 'file.json'
$.parseJSON(
'['
+ ' '
+ ' "type": "firsttype",'
+ ' "text": '
+ ' "id": "content"'
+ ' '
+ ' ,'
+ ' '
+ ' "type": "secondtype",'
+ ' "text": '
+ ' "id": "other"'
+ ' '
+ ' '
+ ']'
)
);
doJsonThing();
/* END UNIT TEST */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
【讨论】:
【参考方案4】:由于其他答案涵盖了您应该考虑的大部分内容,我想我只会针对您的实际问题发布解决方案。 :)
您想遍历任意 JSON 并搜索特定键,并且可能对其值有条件。然后,您要返回指定键的所有值(如果指定,则通过您的条件)。
假设你有以下 json:
"hello": "some text",
"object":
"key1": "hello!",
"key2": "Bye!"
,
"array": [
"some_key1": "blah blah blah",
"some_key2": 24
,
"some_key1": "ghiojd",
"some_key2": 13
],
"numeric_array": [2, 3, 4, 5]
这个sn-p会在上面的json中搜索some_key1
,它的值以blah
开头:
function regexpConditionFactory(regex)
return function(value) return regex.test(value); ;
function searchObjectForKey(obj, key, condition, result)
if ($.isPlainObject(obj))
if (obj.hasOwnProperty(key))
if (!condition || ($.isFunction(condition) && condition(obj[key])))
result.push(obj[key]);
if ($.isPlainObject(obj) || $.isArray(obj))
for (var k in obj)
if (obj.hasOwnProperty(k))
searchObjectForKey(obj[k], key, condition, result);
$.getJSON('file.json', function(data)
var res = [];
searchObjectForKey(data, 'some_key1', regexpConditionFactory(/^blah/), res);
$('<ul/>',
'class': 'my-new-list',
'html': res.map(function(value) return '<li>' + value + '</li>'; ).join('')
).appendTo('body');
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
【讨论】:
以上是关于我可以在 $.getJSON 函数中使用递归 JavaScript 函数吗?的主要内容,如果未能解决你的问题,请参考以下文章