JavaScript数组与对象排序详解:从基础到字符串数字处理
本文详解JavaScript中数组排序机制。通过sort()方法及自定义比较函数,解决数字、字符串及数组对象的排序问题。重点解析当对象属性值为字符串形式的数字时,如何通过Number转换与isNaN判断实现正确的数值排序,避免ASCII码比较导致的错误。
普通数组排序机制
一、普通数组排序
在JavaScript中,可以使用sort()方法对数组进行排序。该方法接受一个可选参数,即用于确定元素顺序的比较函数。若省略此参数,数组元素将默认按照ASCII字符编码的顺序进行排列。例如:
var arr = ["a", "b", "A", "B"];
arr.sort();
console.log(arr);//["A", "B", "a", "b"]
由于大写字母A和B的ASCII值分别为65和66,而小写字母a和b的ASCII值分别为97和98,因此上述代码的输出结果为 ["A", "B", "a", "b"] 。
那么,如果数组元素是数字,排序结果会如何呢?
var arr = [15, 8, 25, 3];
arr.sort();
console.log(arr);//[15, 25, 3, 8]
实际输出结果为 [15, 25, 3, 8] 。这是因为sort()方法在排序前会调用每个数组项的toString()方法将其转换为字符串,随后对生成的字符串进行字典序排序。尽管数值15大于3,但在字符串比较中,"15"会排在"3"之前。这通常不符合预期,此时需要利用sort()方法的参数,即传入一个比较函数来解决。
比较函数接收两个参数:若第一个参数应排在第二个参数之前,则返回负数;若两者相等,返回0;若第一个参数应排在第二个参数之后,则返回正数。示例如下:
var arr = [23, 9, 4, 78, 3];
var compare = function (x, y) {//比较函数
if (x < y) {
return -1;
} else if (x > y) {
return 1;
} else {
return 0;
}
}
console.log(arr.sort(compare));
最终结果为 [3, 4, 9, 23, 78] ,达到了预期的排序效果。若需实现降序排列,只需调整比较函数的返回值符号即可:
var compare = function (x, y) {
if (x < y) {
return 1;
} else if (x > y) {
return -1;
} else {
return 0;
}
}
需要注意的是,无法直接使用比较函数来比较无法转换为数字的字符串与数字之间的大小关系:
var arr = ["b", 5]; console.log(arr.sort(compare))
输出结果为 ["b", 5] 。这是因为比较函数在运算时会尝试将字符串转换为数字,而字符串"b"无法转换为有效数字,导致比较失败。若不使用比较函数,则依据ASCII值进行比较,结果变为 [5, "b"] 。
数组对象属性排序
二、数组对象排序
若数组元素为对象,且需根据对象的特定属性进行排序,处理方式与前述比较函数类似:
var arr = [{name: "zlw", age: 24}, {name: "wlz", age: 25}];
var compare = function (obj1, obj2) {
var val1 = obj1.name;
var val2 = obj2.name;
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
}
console.log(arr.sort(compare));
输出结果为 [Object { name="wlz", age=25}, Object { name="zlw", age=24}] ,可见数组已按name属性完成排序。我们可以对上述比较函数进行封装改造:
var compare = function (prop) {
return function (obj1, obj2) {
var val1 = obj1[prop];
var val2 = obj2[prop];if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
}
}
若需按age属性排序,只需调用 arr.sort(compare("age")) 即可。
然而,对age属性排序时需特别注意:若age属性值为数字,排序结果符合预期;但在实际开发中,从服务器返回的数据往往将属性值作为字符串传递。现将上述数组修改为:
var arr = [{name: "zlw", age: "24"}, {name: "wlz", age: "5"}];
这里将age属性由数字改为字符串,并将第二项的age值设为 "5" 。再次调用 arr.sort(compare("age")) 后,结果为:
[Object { name="zlw", age="24"}, Object { name="wlz", age="5"}]
我们的期望是5排在25前面,但是结果不是。这是因为当两个数字字符串比较大小时,会比较它们的ASCII值大小,比较规则是:从第一个字符开始,顺次向后直到出现不同的字符为止,然后以第一个不同的字符的ASCII值确定大小。所以"24"与"5"比较大小时,先比较”2“与"5"的ASCII值,显然”2“的ASCII值比"5"小,即确定排序顺序。
为此,我们需要对比较函数进行进一步优化:
var compare = function (prop) {
return function (obj1, obj2) {
var val1 = obj1[prop];
var val2 = obj2[prop];
if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
val1 = Number(val1);
val2 = Number(val2);
}
if (val1 < val2) {
return -1;
} else if (val1 > val2) {
return 1;
} else {
return 0;
}
}
}
在比较函数中,首先通过 Number(val1) 将属性值转换为数字,并利用 !isNaN(Number(val1)) 判断转换结果是否为有效数字(排除NaN情况)。若转换后的值为数字,则基于转换后的数值进行比较,从而得到正确排序结果。调用 arr.sort(compare("age")) 后得到:
[Object { name="wlz", age="5"}, Object { name="zlw", age="24"}]
由此可见,数组已按正确的数值顺序排列。
本文内容属于基础范畴,技术深度有限,主要源于近期项目中遇到的数组对象排序需求,特此整理分享,希望能对遇到类似问题的开发者有所帮助。
什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
