do...while循环中条件判断函数错误引发无限循环问题排查
先直接点出导致你代码无限循环的核心问题,再给你修正方案:
1. while条件里的箭头函数没有被执行
你现在写的while( () => { ... } )中,括号里是一个箭头函数定义,而不是执行这个函数得到返回值。在JavaScript中,函数对象本身属于“真值”(truthy),所以这个条件永远为true,循环自然会无限执行下去。
你需要把这个函数改成立即执行的表达式,也就是在函数后面加():
while( (() => { // 你的判断逻辑 })() )
2. forEach里的return无法终止外层函数的判断
就算你修复了第一个问题,里面的forEach回调里的return true也达不到你想要的效果——因为forEach的回调是独立的函数,回调里的return只会终止当前这一次回调的执行,不会中断整个forEach的遍历,更不会让外层的箭头函数直接返回true。
所以不管数组里有没有szint === 0的元素,你的箭头函数最后都会执行return false,这会导致循环只执行一次就停止(修复第一个问题后),显然不符合你“直到所有元素szint不为0”的需求。
正确的写法应该是这样
我们可以用数组的some()方法替代forEach,some()会遍历数组,只要找到第一个满足条件的元素就立即返回true并停止遍历;如果没有满足条件的元素,返回false。这完美匹配你判断“是否还有元素szint为0”的需求。
同时,直接用some()的结果作为while条件,不需要额外的箭头函数,代码更简洁:
do { kategoriak.forEach(elem => { elem.child.forEach(child => { kategoriak.forEach(ell => { if(child === ell.id && elem.szint !== 0){ ell.szint = elem.szint + 1 } }) }) }) } while( kategoriak.some(elem => elem.szint === 0) )
额外的优化建议
你的嵌套三层forEach循环效率较低,尤其是数组元素较多时。可以先把kategoriak转成以id为键的映射,这样查找元素会快很多:
// 先创建id到元素的映射表 const kategoriMap = new Map(kategoriak.map(elem => [elem.id, elem])) do { kategoriak.forEach(elem => { if (elem.szint === 0) return; // 跳过还未处理的元素 elem.child.forEach(childId => { const ell = kategoriMap.get(childId); if (ell && ell.szint === 0) { // 只更新未处理的元素 ell.szint = elem.szint + 1; } }) }) } while( kategoriak.some(elem => elem.szint === 0) )
这样不仅减少了不必要的遍历,还避免了重复处理已设置过szint的元素,逻辑更清晰,执行效率也更高。
内容的提问来源于stack exchange,提问作者user9686855

