有時處理數據需要遞歸,或者遍歷,同時需要判定,若是中途滿足了一些條件,就退出遞歸
如下數據:
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;
}
})
}
}