JavaScript数组排序:sort方法与手动实现全解析
JavaScript数组排序是前端开发中的常见需求。本文详细讲解原生`sort()`方法的自定义排序规则,特别是数字排序的正确写法,并剖析手动实现排序时关于引用类型复制数组的关键知识点,附带完整代码与运行效果。
使用原生sort方法进行自定义排序
JavaScript数组内置了 sort() 方法,但在处理数值数组时,直接使用该方法会导致未按数值大小排序的结果。这是因为 sort() 默认将所有元素转换为字符串,并按照UTF-16码元的顺序进行排序(即字母/字典序)。
为了让数字正确排序,必须传入一个比较函数作为参数。该函数接收两个参数 a 和 b:
- 升序排列:返回
a - b。当结果为负数时,a排在b前面;为正数时,b排在a前面。 - 降序排列:返回
b - a。
var arr = [45,98,67,57,85,6,58,83,48,18];
console.log('原数组');
console.log(arr);
console.log('sort方法从小到大排序');
console.log(arr.sort(function(a,b){return a-b}));
console.log('sort方法从大到小排序');
console.log(arr.sort(function(a,b){return b-a}));
上述代码展示了标准的“标准答案”做法。需要注意的是,sort() 会直接修改原数组。如果希望保留原数组不变,需要先对数组进行深拷贝或浅拷贝(针对非对象元素的一维数组)。
手动实现排序算法
为了理解排序逻辑,我们可以通过编写自定义函数来实现排序。以下展示一种基于选择排序思想的手动实现方式:每次从未排序部分中找到最小(或最大)值,放入新数组中,并从原副本中移除该值。
第1步:定义辅助函数提取极值
我们需要两个辅助函数,分别用于获取数组中最小的值和最大的值,并记录其索引,以便后续删除。
// 找数组中最小的值
function arrMinNum(arr){
var minNum = Infinity, index = -1;
for (var i = 0; i < arr.length; i++) {
if (arr[i] < minNum) {
minNum = arr[i];
index = i;
}
};
return {"minNum":minNum,"index":index};
}
// 找数组中最大的值
function arrMaxNum(arr){
var maxNum = -Infinity, index = -1;
for (var i = 0; i < arr.length; i++) {
if (arr[i] > maxNum) {
maxNum = arr[i];
index = i;
}
};
return {"maxNum":maxNum,"index":index};
}
这里使用了JSON对象格式返回多条数据(数值和索引),这是JS函数返回多个值的常用技巧。
第2步:构建排序主函数
在构建排序函数前,必须解决引用类型的问题。JavaScript中Array是引用类型,直接赋值 var arrOld = arr 只会复制引用,导致操作副本时影响原数组。为了保证原数组不被修改,需使用 concat() 或 slice(0) 进行复制。
// 返回数组从小到大排序结果
function arrSortMinToMax(arr){
var arrNew = [];
// 复制数组,避免修改原数组
var arrOld = arr.concat();
for (var i = 0; i < arr.length; i++) {
var minInfo = arrMinNum(arrOld);
arrNew.push(minInfo.minNum);
// 从副本中移除已选取的最小值
arrOld.splice(minInfo.index, 1);
};
return arrNew;
}
// 返回数组从大到小排序结果
function arrSortMaxToMin(arr){
var arrNew = [];
// 同样需要复制数组
var arrOld = arr.slice(0);
for (var i = 0; i < arr.length; i++) {
var maxInfo = arrMaxNum(arrOld);
arrNew.push(maxInfo.maxNum);
// 从副本中移除已选取的最大值
arrOld.splice(maxInfo.index, 1);
};
return arrNew;
}
完整测试代码如下,调用上述函数:
var arr = [45,98,67,57,85,6,58,83,48,18];
console.log('原数组');
console.log(arr);
console.log('for方法从小到大排序');
console.log(arrSortMinToMax(arr));
console.log('for方法从大到小排序');
console.log(arrSortMaxToMin(arr));
// 验证原数组未被修改
console.log('原数组是否被修改?', arr);
关键知识点总结
- 引用类型陷阱:在对数组进行操作且不希望改变原数组时,务必使用
arr.concat()或arr.slice(0)创建副本。splice()方法常用于就地修改数组,需谨慎使用。 - 性能差异:手动实现的这种“查找最小值并移除”的方法时间复杂度为 $O(n^2)$,在处理大量数据时效率远低于V8引擎优化的原生
sort()(通常基于Timsort等高效算法)。因此,在生产环境中推荐优先使用原生API。 - 返回值处理:当函数需要返回相关连的多值时,返回包含键值对的对象比返回数组更语义化且易于解构。
以上就是JavaScript sort数组排序方法和自我实现排序方法的详细内容,更多关于JavaScript数组操作技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









