项目中常常会对开发返回的json数据进行遍历,然后更新页面,如果数据只是简单的一层结构,只需一个for循环即可搞定,但如果数据存在较深且不确定的层次,此时就需要使用递归配合循环来搞定,先看下模拟的数据格式:
//json数据
var json = {
status: 'success',
data: [
{
status: 0,
title: '文件夹1',
data: [
{
status: 0,
title: '文件夹2',
data: [
{
status: 0,
title: '文件夹3',
data: [
{
status: 0,
title: '文件夹4',
data: []
},
{
status: 0,
title: '文件夹4',
data: []
}
]
},
{
status: 0,
title: '文件夹3',
data: []
}
]
},
{
status: 0,
title: '文件夹2',
data: []
}
]
},
{
status: 1,
title: '文件1',
}
]
};
对于上面这种深层次的数据结构,普通的循环是无法搞定的,此时可以提取重复处理的代码片段,然后使用递归 即可搞定,直接看代码:
/**
* 递归遍历数据
*/
function recursion(data) {
var i = 0,
len = data.length,
j, item, current, flag;
for (; i < len; i++) {
item = data[i];
for (j in item) {
current = item[j];
//是否数组判断
flag = (Object.prototype.toString.call(current) === '[object Array]') ? true : false;
if (flag) {
recursion(current);
} else {
//这里执行对数据的相应操作
console.log(current);
}
}
}
}
//调用
recursion(json.data);
一个类似的应用是DOM节点的游走,可以遍历整个文档所有节点,包括子节点,看如下代码:
/**
* 节点遍历
*/
function nodeWalk(node, fn) {
var re = arguments.callee; //引用函数本身
if (node.nodeType === 1) {
//处理节点
fn.call(node, node);
}
node = node.firstChild;
while (node) {
re(node, fn);
node = node.nextSibling;
}
}
//调用
nodeWalk(document.body, function(n){
console.log(this.nodeName);
});
还有一种典型用例是,对于多行的input需要往后端ajax实时验证输入内容的时候,普通的for循环已不能解决问题,需要在ajax请求成功的回调函数里进行递归调用,直接看示例代码:
//初始化
var nodeList = $('#test input:text'),
n = 0;
/**
* 递归验证
*/
(function recursionCheck(node) {
var v = node.value,
nextNode = nodeList[++n];
//ajax请求服务端验证
$.ajax({
'url': 'xxxxx.do',
'data': 'xxxxxx',
'dataType': 'json',
'success': function(data){
//验证成功,递归调用代码验证下一个node
if (data.value === v) {
//判断节点是否存在
if (nextNode) {
recursionCheck(nextNode);
} else {
alert('验证通过');
}
}
//验证不成功,结束执行,给出错误提示
else {
alert('数据验证不正确');
}
}
});
})(nodeList[n]);
Der's Blog
以前也这么递归遍历数据,后来发现不用递归也可以做。复习了一下数据结构的东西。