JS递归实现数组无重复随机采样返回undefined问题排查
问题根源
返回undefined的核心原因是递归调用的返回值没有逐层向外传递:JavaScript中如果函数跑完所有逻辑都没碰到显式的return语句,默认就会返回undefined。
错误代码的执行逻辑
当随机抽中的字母已经在used_letters数组里时,代码会进入重复判断分支:
- 这里你只是调用了
pick_random_letter(),既没存储这个递归调用的返回值,也没把结果返回给当前层的调用方 - 拿一个典型执行流程举例:
- 最外层调用
pick_random_letter(),随机抽到已经用过的A,进入重复判断分支 - 分支里触发递归,内层调用抽到了没使用过的B,走else分支返回
"B" - 这个返回值只会回到上一层递归的调用位置,但上一层分支没做任何返回操作,函数执行到末尾直接结束,默认返回
undefined给最外层的调用代码,最后你拿到的结果就是undefined
- 最外层调用
加return后正常运行的原理
写return pick_random_letter()的时候,相当于把内层递归拿到的有效结果,直接作为当前层函数的返回值向上传递:
- 不管递归深入了多少层,每一层都会把内层返回的未重复字母继续往外层抛,直到最开始的调用位置,自然就能拿到正确的选中值
- 额外说明:
return是操作符不是函数,你写的return(pick_random_letter())里的括号不影响逻辑,和return pick_random_letter()效果完全一致。
存在问题的代码
let letters = [ { name: 'A' }, { name: 'B' }, { name: 'C' }, { name: 'D' }, ] let used_letters = []; function pick_random_letter(){ let random = Math.floor(Math.random() * letters.length); let next_letter = letters[random].name; if (used_letters.includes(next_letter)){ if (used_letters.length == letters.length) used_letters = []; pick_random_letter(); // 这里没有return,内层返回值被直接丢弃 }else{ used_letters.push(next_letter); return next_letter; } } for (let i = 0; i < 4; i++){ let random_letter = pick_random_letter(); console.log(random_letter); console.log(used_letters); }
可正常运行的代码
let letters = [ { name: 'A' }, { name: 'B' }, { name: 'C' }, { name: 'D' }, ] let used_letters = []; function pick_random_letter(){ let random = Math.floor(Math.random() * letters.length); let next_letter = letters[random].name; if (used_letters.includes(next_letter)){ if (used_letters.length == letters.length) used_letters = []; return pick_random_letter(); // 把内层递归结果逐层向外返回 }else{ used_letters.push(next_letter); return next_letter; } } for (let i = 0; i < 4; i++){ let random_letter = pick_random_letter(); console.log(random_letter); console.log(used_letters); }
内容的提问来源于stack exchange,提问作者Pypax
相关产品推荐
相关产品推荐

