有时处理数据需要递归,或者遍历,同时需要判定,若是中途满足了一些条件,就退出递归
如下数据:
var node = [
{ name:'a',leaf:false},
{ name:'b',leaf:true,
children:[
{name:'b1',leaf:true},
{name:'b2',leaf:true}
],
},
{ name:'c',leaf:false}
];
数组对象.forEach()
而forEach
可枚举每一个数组元素,但并不支持类似for循环的break语法,中断循环
例如,上面的例子我们使用下
function A() {
node.forEach((x)=>{
if(x.leaf) return console.log('终止');
else console.log(x.name);
});
}
在控制台里执行:
而如果采用for循环
function B() {
for(var i=0;i<node.length;i++) {
var x = node[i];
if(x.leaf) return console.log('终止');
else console.log(x.name);
}
}
在控制台里输出:
那问题来了:
又想使用forEach,又想中断咋办?
方法一:.复写forEach方法:
过程:略(自行百度)
方法二:使用抛出异常
try{
node.forEach((x)=>{
if(x.leaf) throw '终止'
else console.log(x.name);
});
}catch(r) {
console.log(r)
}
那如果想进行稍微复杂点的递归后回调,应该这么处理
function A(a) {
if(a.leaf) throw a;
else if(a.children){
a.children.forEach((x)=>{
throw A(x);
})
}
}
function B(b) {
b.forEach((x)=>{
try{
A(x)
}catch(r) {
throw r;
}
})
}
function C() {
try{
B(node)
}catch(r) {
console.log(r)
}
}
然后控制台里执行:
注意:如果把B方法更改了
function B(b) {
b.forEach((x)=>{
throw A(x);//直接抛出A
})
}
控制台里执行 无返回结果
我们再尝试把数据改复杂点
var node = [
{ name:'a',leaf:false},
{ name:'b',leaf:false,
children:[
{name:'b1',leaf:false},
{name:'b2',leaf:false,
children:[
{name:'b21',leaf:false},
{name:'b22',leaf:true,}
],
}
],
},
{ name:'c',leaf:false}
];
这是再次执行C()会发现,没有结果抛出
需要改造A方法:
function A(a) {
if(a.leaf) throw a;
else if(a.children){
a.children.forEach((x)=>{
try{
A(x) //递归时调用 也要继续抛出异常
}catch(r) {
throw r;
}
})
}
}