You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

问题出在哪?

  1. 重复递归调用:你在处理目录时调用了两次walk(fullPath, counter),但第二次调用的返回值没有赋值给counter,导致这部分递归的计数直接丢失了
  2. 值传递的坑: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:07:49