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

JavaScript嵌套函数for循环调用导致选择排序结果异常

问题表现

使用JavaScript实现选择排序时运行结果不符合预期:

  • 预期sortArray()返回由6个"5"组成的数组[5,5,5,5,5,5]
  • 实际运行仅返回包含单个值5的数组
  • 测试发现注释掉代码行smallest_index = find_smallest(nums)后,即可得到预期输出

原始实现代码如下:

let nums = [2, 1, 3, 4, 5, 6];

function sortArray(nums) {
  let arr = new Array();
  let smallest_index;
  for (i = 0; i < nums.length; i++) {
    smallest_index = find_smallest(nums);
    arr.push("5");
  }

  return arr;
}

function find_smallest(arr) {
  let smallest = arr[0];
  let smallest_index = 0;

  for (i = 1; i < arr.length; i++) {
    if (arr[i] < smallest) {
      console.log("this");
      smallest = arr[i];
      smallest_index = i;
    }
  }
  return smallest_index;
}

console.log(sortArray(nums));
问题根因

核心错误是循环变量未声明导致全局作用域污染:

  • 两个函数内的for循环都没有用let/const声明循环变量i,直接对i赋值的写法在JavaScript中会把i注册为全局作用域的共享变量,两个函数操作的是同一个i
  • 第一次进入sortArray的循环时,全局i初始值为0,随即调用find_smallest;find_smallest内部的循环会从i=1一直遍历到i等于数组长度(即6)才退出
  • 从find_smallest返回sortArray的循环判断逻辑时,全局i的值已经是6,判断i < nums.length(6 < 6)结果为false,循环直接终止,仅执行了1次push操作,因此最终数组只有1个元素。这也是注释掉find_smallest调用后,循环能正常执行6次得到预期结果的原因。

额外说明:当前代码还未实现选择排序的完整逻辑,即使修复了循环变量问题,每次调用find_smallest拿到的都是原数组第一个最小值的索引,没有把已找到的最小值从原数组移除,也无法完成正确的排序。

修复方案
  1. 所有for循环的循环变量统一用let声明,做块级作用域隔离,彻底避免变量跨函数污染
  2. 如果要实现完整选择排序逻辑,需要在每次找到最小值索引后,将对应元素从待排序数组中删除,再推入结果数组,保证下一次查找能找到剩余元素里的最小值

修复后的可运行代码:

let nums = [2, 1, 3, 4, 5, 6];

function sortArray(nums) {
  // 浅拷贝入参,避免修改外部原数组
  let sourceArr = [...nums];
  let sortedArr = new Array();
  let smallest_index;
  // 声明块级作用域循环变量
  for (let i = 0; i < nums.length; i++) {
    smallest_index = find_smallest(sourceArr);
    // 移除已找到的最小值,推入结果数组
    sortedArr.push(sourceArr.splice(smallest_index, 1)[0]);
  }
  return sortedArr;
}

function find_smallest(arr) {
  let smallest = arr[0];
  let smallest_index = 0;
  // 声明块级作用域循环变量
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < smallest) {
      smallest = arr[i];
      smallest_index = i;
    }
  }
  return smallest_index;
}

console.log(sortArray(nums)); // 正确排序输出 [1,2,3,4,5,6]

如果只是要实现测试阶段返回6个"5"的效果,只需要给两个循环的i加上let声明即可,不需要补全排序逻辑。

内容的提问来源于stack exchange,提问作者Exodus Reed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:06:22