关于JavaScript递归函数capitalizeFirst的两处疑问求助
递归函数capitalizeFirst的疑问解答
原代码
function capitalizeFirst(arr) { if (arr.length === 1) { return [arr[0].toUpperCase()] } let res = capitalizeFirst(arr.slice(0, -1)) res.push(arr.slice(arr.length - 1)[0].toUpperCase()) return res } console.log(capitalizeFirst(['dog', 'car', 'horse']))
疑问点
- 基准情况中为什么要返回
[arr[0].toUpperCase()],而非直接返回arr[0].toUpperCase()? - 为什么要对arr进行两次slice操作:一次是
let res = capitalizeFirst(arr.slice(0, -1)),另一次是res.push(arr.slice(arr.length - 1)[0].toUpperCase())?
疑问1解答
递归的核心要求是每一层调用的返回值类型必须统一,否则上层调用无法正确处理结果。
这个函数的目标是返回一个「所有元素首字母大写的数组」,如果基准情况直接返回字符串(arr[0].toUpperCase()),那递归到最底层时返回的是单个字符串,上层调用拿到这个字符串后执行res.push()就会直接报错——因为字符串没有push方法。
返回数组[arr[0].toUpperCase()],才能保证每一层递归都返回数组,上层可以正常用push把当前层处理的元素加进去,最终得到完整的结果数组。
疑问2解答
两次slice是递归拆解问题的关键,作用完全不同:
- 第一次
arr.slice(0, -1):把原数组切掉最后一个元素,生成新数组传给下一层递归。比如原数组是['dog','car','horse'],第一次调用会传['dog','car']进去,直到数组只剩一个元素触发基准情况。这一步是把大问题拆成更小的子问题。 - 第二次
arr.slice(arr.length - 1):取出原数组的最后一个元素(slice(arr.length-1)返回只包含最后一个元素的数组),用[0]提取出这个元素,转成首字母大写后push到递归返回的结果数组里。这一步是把当前层的处理结果合并到子问题的结果中。
其实第二次slice可以简化成arr[arr.length-1],效果完全一样,原代码这么写可能是个人习惯,但逻辑没问题。
内容的提问来源于stack exchange,提问作者Akhror Khamidov
相关产品推荐
相关产品推荐

