
本文讲解 `getfirsthalf` 函数中因忽略递归返回值导致结果未更新的问题,指出必须用 `return getfirsthalf(firsthalf)` 显式传递最终结果,否则递归调用的返回值会被丢弃,函数始终返回初始分割出的首半数组。
在实现一个递归获取数组“最深层首半部分”(即不断取首半,直到长度为 1)的函数时,一个常见却容易被忽视的错误是:调用了递归但没有返回其结果。这会导致函数虽然执行了多层递归,但最终仍返回最外层计算出的 firstHalf,而非递归终止时的最终结果。
来看原始代码的问题所在:
const getFirstHalf = function (array) {
const firstHalf = [];
for (let i = 0; i < Math.trunc(array.length / 2); i++) {
firstHalf.push(array[i]);
}
if (firstHalf.length !== 1) {
getFirstHalf(firstHalf); // ❌ 错误:调用递归但未返回其结果!
}
return firstHalf; // ✅ 总是返回当前层的 firstHalf,与递归无关
};以 getFirstHalf([1,2,3,4,5,6,7,8]) 为例,执行流程如下:
- 第 1 层:array = [1..8] → firstHalf = [1,2,3,4] → 进入 if,调用 getFirstHalf([1,2,3,4]),但不接收也不返回它的结果;
- 第 2 层:array = [1,2,3,4] → firstHalf = [1,2] → 再次调用 getFirstHalf([1,2]);
- 第 3 层:array = [1,2] → firstHalf = [1] → firstHalf.length === 1,跳过 if,返回 [1];
- 但第 2 层并未 return 这个 [1],而是继续执行 return firstHalf → 返回 [1,2];
- 第 1 层同理,最终返回 [1,2,3,4] —— 正是用户观察到的意外结果。
✅ 正确写法:在递归分支中显式 return 递归调用的结果:
const getFirstHalf = function (array) {
// 边界处理:空数组或单元素直接返回
if (array.length <= 1) return [...array]; // 防止修改原数组,返回副本
const firstHalf = [];
for (let i = 0; i < Math.trunc(array.length / 2); i++) {
firstHalf.push(array[i]);
}
// ✅ 关键修复:递归结果必须被 return
if (firstHalf.length > 1) {
return getFirstHalf(firstHalf);
}
return firstHalf;
};
// 测试
const myArray = [1, 2, 3, 4, 5, 6, 7, 8];
console.log(getFirstHalf(myArray)); // 输出: [1]? 补充优化建议:
- 使用 Math.floor(array.length / 2) 或解构赋值(如 array.slice(0, Math.floor(array.length / 2)))替代手动循环,更简洁安全;
- 添加输入校验(如 !Array.isArray(array) 报错)提升健壮性;
- 注意:Math.trunc() 在非负数时等价于 Math.floor(),但为明确语义,推荐 Math.floor()。
总结:递归函数中,每一层的返回值都需被上一层显式接收并返回,否则递归链断裂,逻辑失效。这是理解递归执行流与控制流的关键一课。










