JavaScript递归函数返回列表全为相同条目的原因排查
递归生成课程组合笛卡尔积时返回列表所有对象重复问题排查
问题根因
你遇到的所有返回条目完全相同的问题,核心原因是JavaScript中对象为引用类型,递归全程没有做对象拷贝,所有分支操作、返回的都是内存中的同一个对象。
具体错误点有两处:
- 递归传参时直接传递
dictSoFar的引用,没有为每个组合分支创建独立的对象副本。for循环中每次修改dictSoFar的属性值,都会同步修改所有递归分支中持有的同一个对象,之前已经存入结果数组的对象值会被后续循环的修改覆盖。 - 递归基准条件直接返回
[dictSoFar],存入结果数组的是同一个对象的引用,不是独立的对象实例。等所有递归循环跑完,这个公共对象里存的是最后一次遍历到的组合值,最终数组里120个指向同一内存地址的引用,打印出来自然全是相同内容。
另外你原代码中用filter过滤当前课程的写法没有必要,每次处理的都是列表首元素,直接用slice(1)截取剩余课程列表即可,性能更高也不会出现引用判断的异常。
修正后代码
function recursiveFunction(listOfCourses, dictSoFar) { // 基准条件:课程列表遍历完成,返回当前组合的独立对象副本 if (!listOfCourses.length) { return [{ ...dictSoFar }] } const arraySoFar = [] const currentCourse = listOfCourses[0] // 直接截取剩余待处理课程,无需filter遍历 const restCourses = listOfCourses.slice(1) for (const combo of currentCourse.possibleCombos) { // 每个组合分支创建独立的字典副本,避免跨分支修改污染 const nextDict = { ...dictSoFar, [currentCourse.courseCode]: combo } // 传入独立副本递归处理剩余课程 const branchResult = recursiveFunction(restCourses, nextDict) arraySoFar.push(...branchResult) } return arraySoFar }
验证说明
传入你提供的测试数据运行,返回数组长度为5*4*6=120,每个对象都是独立实例,完整覆盖所有课程可选值的笛卡尔积组合,不会出现条目重复的问题。
内容的提问来源于stack exchange,提问作者Brandon Lei
相关产品推荐
相关产品推荐

