为何同一JS函数中数组升序降序排序后相等比较结果均为true
问题根因分析
代码判断逻辑失效是两个JavaScript语言特性共同导致的:
- 第一个核心问题是
Array.sort()的原地修改特性:sort()方法不会生成新的数组副本,会直接在原数组的内存空间上修改元素顺序,且方法的返回值就是原数组的引用,不是新数组。
执行第一行let asc = arr.sort((a, b) => a - b)时,传入的原数组会被直接修改为升序,此时asc和arr指向同一个内存地址的同一个数组。
紧接着执行第二行let dsc = arr.sort((a, b) => b - a)时,同一个数组又被直接修改为降序,此时dsc同样指向这个数组,最终arr/asc/dsc三个变量完全指向同一个数组对象,内部元素都是降序排列的状态。 - 第二个核心问题是数组的相等比较规则:JavaScript中数组属于引用类型(特殊对象),使用
==或者===比较两个数组时,不会逐位对比内部元素是否相等,只会判断两个变量是否指向同一个内存地址的同一个对象。
由于三个变量指向同一个数组,arr == asc的判断结果永远为true,完全不会走到后续的降序判断、无序判断分支。
修正方案
要正确实现判断逻辑,需要先复制原数组再做排序,避免修改原数组、避免引用相同,同时逐位对比数组元素判断排序方向,参考代码如下:
function isSortedAndHow(arr) { // 用展开运算符复制原数组后再排序,生成独立的升序、降序参考数组 const ascArr = [...arr].sort((a, b) => a - b); const dscArr = [...arr].sort((a, b) => b - a); // 逐位对比元素和参考数组是否一致 const isAscending = arr.every((item, index) => item === ascArr[index]); const isDescending = arr.every((item, index) => item === dscArr[index]); if (isAscending) { console.log("Ascending , Yes"); } else if (isDescending) { console.log("Descending , Yes"); } else { console.log("No"); } } // 测试用例[25,20,15,30,35]既非纯升序也非纯降序,会正确输出"No" isSortedAndHow([25,20,15,30,35]);
注:如果数组长度较大,生成两个排序副本的方案性能一般,更高效的写法是直接遍历一次原数组,判断相邻元素的大小关系即可,不需要额外排序。
内容的提问来源于stack exchange,提问作者Ahsan Khalid
相关产品推荐
相关产品推荐

