JavaScript中未用var/let声明变量导致归并排序结果异常
问题重现
你编写的归并排序代码在未用var/let声明leftArr、m、sortedArr这些变量时,输出结果为[49, 59],而非预期的[12, 23, 45, 49, 57, 59],添加变量声明后恢复正常。
核心原因:隐式全局变量的递归干扰
在JavaScript中,函数内未声明的变量会自动成为全局对象的属性,所有函数调用(包括递归调用)都会共享这个全局变量,这直接破坏了归并排序的递归逻辑:
递归调用中的变量覆盖
当第一次调用mergeSort(arr)时,执行leftArr = mergeSort(arr.splice(0, m)),此时leftArr是全局变量。进入递归处理左半数组[57,23,45]时,这个递归函数里又会给全局的leftArr赋值(比如处理[57,23,45]时,会拆分出左数组[57],给leftArr赋值为[57]),这直接覆盖了外层递归中leftArr原本应该存储的[57,23,45]的排序结果。当外层递归继续执行
rightArr = mergeSort(arr)时,原本的左半数组结果已经被覆盖,后续mergeArrays拿到的leftArr是最后一次递归赋值的内容,而非当前层级应该保留的左半部分排序结果,最终导致合并逻辑完全错误,只输出了最底层递归的小部分数组。对比声明变量的情况
用let/var声明变量后,leftArr、m会成为当前函数调用的局部变量,每个递归层级的变量都是独立的,不会互相覆盖,递归过程中每个层级的左、右数组结果都能正确保留,最终完成完整的归并排序。
额外提示
代码中的sortedArr同样未声明,虽然这里没有直接导致错误,但它也是全局变量,会在多次mergeArrays调用中被覆盖,属于不良编码实践,建议统一用let声明。
内容的提问来源于stack exchange,提问作者Sapthaka

