如何在JavaScript递归函数调用中正确递增计数器?
递归文件遍历中计数器递增异常的解决办法
嘿,我完全懂你自学JavaScript时遇到的这个计数器坑!递归遍历文件时,计数器总是乱跳甚至重置,确实让人头大。你说的没错,问题根源就是递归调用时计数器的传递和重置逻辑出了问题。
先看看你原来的代码和遇到的问题:
原问题代码
function walk(dir, counter = 0) { fs.readdirSync(dir).forEach(file => { let fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { counter = walk(fullPath, counter); walk(fullPath, counter); // 这里重复调用了walk,还没更新counter! console.log('dir'); } else { let size = fs.statSync(fullPath).size; listFiles.write(fullPath + " (" + size + ")\n"); ++counter; console.log(counter); } }); return counter; } walk(copyFrom);
异常输出序列
2,3,4,5,6,7,dir,5,6,8,9,10,11,12,13,dir,11
问题出在哪?
- 重复递归调用:你在处理目录时调用了两次
walk(fullPath, counter),但第二次调用的返回值没有赋值给counter,导致这部分递归的计数直接丢失了 - 值传递的坑:JavaScript的基本类型(比如数字)是值传递,递归里修改的是
counter的副本,就算你赋值了一次,重复调用还是会打乱计数逻辑
修复后的解决方案
function walk(dir) { let n = 0; // 把计数器放在外层,作为闭包变量,所有递归分支共享 function walk(dir) { fs.readdirSync(dir).forEach(file => { ++n; console.log(n); let fullPath = path.join(dir, file); if (fs.lstatSync(fullPath).isDirectory()) { --n; // 遍历到目录时,抵消掉刚才的自增(我们要统计的是文件) walk(fullPath); console.log('dir'); } else { let size = fs.statSync(fullPath).size; listFiles.write(fullPath + " (" + size + ")\n"); } }); } walk(dir); return n; // 最后返回统计的总次数 }
为什么这个方案能解决问题?
- 闭包共享变量:计数器
n被外层函数持有,内层的递归walk可以直接修改它,所有递归调用都用同一个计数器,不会出现重置或值丢失的情况 - 修正计数逻辑:遇到目录时先自增再递减,确保只有文件会被计入统计,目录本身不会干扰计数
- 去掉重复调用:每个目录只遍历一次,逻辑更简洁,避免了重复遍历导致的计数混乱
内容的提问来源于stack exchange,提问作者Puka
相关产品推荐
相关产品推荐

