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

为何未使用变量赋值的JS递归数组切片代码会触发无限循环?

问题原因解答

核心问题根源:全局变量污染

你两段代码中的halfway变量都没有使用var/let/const声明,属于隐式创建的全局变量,所有函数调用共享同一个halfway值,不存在函数级的局部作用域隔离,这是问题的根本原因。

无限循环代码的执行逻辑

触发死循环的核心是参数计算时机晚于第一个递归调用,执行顺序如下:

  1. 首次调用half([1,2,3,4,5]),全局halfway被赋值为2,打印数组后,先执行第一个递归调用half(arr.slice(0,2))(也就是half([1,2]))
  2. 进入half([1,2]),全局halfway被赋值为1,打印数组后,先执行第一个递归调用half(arr.slice(0,1))(也就是half([1]))
  3. 进入half([1]),第一行就把全局halfway赋值为Math.floor(1/2)=0,因为数组长度等于1,不进入递归直接返回
  4. 回到half([1,2])的第二个递归调用,此时需要计算arr.slice(halfway),但全局halfway已经被改成了0,所以arr.slice(0)得到的还是[1,2],相当于又调用了一次half([1,2]),就此进入无限循环。

第二段代码正常运行的原因

第二段代码的差异是提前计算好了两个递归参数并保存,不会被后续的递归调用修改:

  1. 进入half([1,2])时,全局halfway被赋值为1,第一时间计算了a = arr.slice(0,1)、b = arr.slice(1),把两个参数值提前存到了局部变量a和b里
  2. 后续执行half(a)的时候,哪怕全局halfway被改成了0,也不会影响已经计算完成的b的值,第二个递归调用直接传入已经算好的b也就是[2],不会重新计算slice,所以递归可以正常终止。

修复方案

只需要把halfway声明为函数局部变量即可,两段代码都会正常运行:

function half(arr) {
  // 加let声明为局部变量,每次函数调用都有独立的halfway
  let halfway = Math.floor(arr.length / 2)
  console.log(arr)
  if (arr.length > 1) {
    half(arr.slice(0, halfway));
    half(arr.slice(halfway));
  }
  return
}

内容的提问来源于stack exchange,提问作者Azeth Nu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:00:05