简单了解JavaScript sort方法


Posted in Javascript onNovember 25, 2019

在平时的业务开发中,数组(Array) 是我们经常用到的数据类型,那么对数组的排序也很常见,除去使用循环遍历数组的方法来排列数据,使用JS数组中原生的方法 sort 来排列(没错,比较崇尚JS原生的力量)。

1、举个栗子

数组中能够直接用来排序的方法有:reverse() 和 sort(),由于 reverse()方法不够灵活,才有了sort()方法。在默认情况下,sort()方法按升序排列数组。

var arr=[1,3,5,9,4];
console.log(arr.sort());
// 输出: [1, 3, 4, 5, 9]

这时发现数据按照从小到大排列,没问题;于是再把数组改成:var arr=[101,1,3,5,9,4,11];,再调用sort()方法打印排序结果。

var arr=[101,1,3,5,9,4,11];
console.log(arr.sort());
// 输出: [1, 101, 11, 3, 4, 5, 9]

这个时候发现数组101,11都排在3前面,是因为 sort() 方法会调用数组的toString()转型方法,然后比较得到的字符串,确定如何排序,即使数组中的每一项都是数值,sort()方法比较的也是字符串。

那么字符串又是怎么排序的呢,是根据字符串的unicode编码从小到大排序的。下面我们尝试打印出数组每一项的unicode编码看一下。

...
// 转码方法
function getUnicode (charCode) {
  return charCode.charCodeAt(0).toString(16);
}
// 打印转码
arr.forEach((n)=>{
 console.log(getUnicode(String(n)))
});

// 输出: 31 31 31 33 34 35 39

惊奇地发现,1,101,11的字符串unicode编码都是31

2、传入比较函数以指定顺序

以上发现sort()方法不是按照我们想要的顺序排序的,那么,怎么解决呢,sort()方法可以接收一个比较函数作为参数,以便指定哪个值位于哪个值前面。

比较函数(compare)接收两个参数,如果第一个参数位于第二个之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数位于第二个之后则返回一个整数。

function compare(value1,value2){
 if (value1 < value2){
  return -1;
 } else if (value1 > value2){
  return 1;
 } else{
  return 0;
 }
}

我们把比较函数传递给sort()方法,在对arr数组进行排列,打印结果如下:

var arr=[101,1,3,5,9,4,11];
console.log(arr.sort(compare));
// 输出: [1, 3, 4, 5, 9, 11, 101];

可以发现排序从小到大没有什么问题。

3、对象数组的排序

sort() 方法通过传入一个比较函数来排序数字数组,但是在开发中,我们会对一个对象数组的某个属性进行排序,例如id,年龄等等,那么怎么解决呢?

要解决这个问题:我们可以定义一个函数,让它接收一个属性名,然后根据这个属性名来创建一个比较函数并作为返回值返回来(JS中函数可以作为值来使用,不仅可以像传递参数一样把一个函数传递给另一个函数,也可以将一个函数作为另一个函数的结果返回,函数作为JS中的第一等公民不是没有原因的,确实很灵活。),代码如下。

function compareFunc(prop){
 return function (obj1,obj2){
  var value1=obj1[prop];
  var value2=obj2[prop];
  if (value1 < value2){
    return -1;
  } else if (value1 > value2){
    return 1;
  } else{
    return 0;
  }
 }
}

定义一个数组users,调用sort()方法传入compareFunc(prop)打印输出结果:

var users=[
  {name:'tom',age:18},
  {name:'lucy',age:24},
  {name:'jhon',age:17},
];
console.log(users.sort(compareFunc('age')));
// 输出结果
[{name: "jhon", age: 17},
{name: "tom", age: 18},
{name: "lucy", age: 24}]

在默认情况下,调用sort()方法不传入比较函数时,sort()方法会调用每个对象的toString()方法来确定他们的次序,当我们调用compareFunc('age')方法创建一个比较函数,排序是按照对象的age属性排序的。

4、XML节点的排序

尽管现在很多后台返回数据就是JSON格式的,很轻量又方便解析。但是之前有个项目因为后台返回的都是XML字符串,前端拿到数据后还得进行序列化,有些需要排序,之前的排序都是把XML转换成数组对象进行排序的,这样做没有什么问题,只不过感觉代码写的很冗余麻烦。后来就突发奇想,xml获取得到也是类数组对象,把类数组对象转换成数组不就可以直接排序了么。

// 1.模拟后端返回的XML字符串
var str=`
<root>
 <user>
  <name>tom</name>
  <age>18</age>
 </user>
 <user>
  <name>lucy</name>
  <age>24</age>
 </user>
 <user>
  <name>jhon</name>
  <age>17</age>
 </user>
<root>
`  
// 2.定义比较函数
function compareFunction(prop){
 return function (a, b) {
   var value1= a.getElementsByTagName(prop)[0].textContent;
   var value2= b.getElementsByTagName(prop)[0].textContent;
   if (value1 < value2){
    return -1;
   } else if (value1 > value2){
    return 1;
   } else{
    return 0;
  }
 }
}
// 3.xml字符串转换成xml对象
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(str, 'text/xml');
var userElements=xmlDoc.getElementsByTagName('user'));
// 4.userElements类数组对象转换成数组再排序
var userElements=Array.prototype.slice.call(xmlDoc.getElementsByTagName('user'));
var _userElements=userElements.sort(compareFunction('age'));
// 5.打印排序后的结果
_userElements.forEach((user)=>{
 console.log(user.innerHTML);
});

打印排序后的结果

简单了解JavaScript sort方法

可以发现,XML节点已经按照age从小到大排序了。

5、总结

JS数组的sort方法因为有了传入比较函数使得排序灵活了许多,还有根据时间,汉字拼音首字母排序等等,我们只要牢记通过传入比较函数明确比较两个对象属性值,通过比较属性值来决定对象的排序顺序即可。自己也是在工作中遇到问题从而发现解决问题的新思路,以上就简单总结这么多了,如有不足,多多指正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
IE6/7/8中Option元素未设value时Select将获取空字符串
Apr 07 Javascript
javascript中关于执行环境的杂谈
Aug 14 Javascript
JS实现控制表格内指定单元格内容对齐的方法
Mar 30 Javascript
酷炫jQuery全屏3D焦点图动画效果
Mar 22 Javascript
js复制内容到剪贴板代码,js复制代码的简单实例
Oct 27 Javascript
原生JS中slice()方法和splice()区别
Mar 06 Javascript
jQuery基于事件控制实现点击显示内容下拉效果
Mar 07 Javascript
微信小程序 本地数据存储实例详解
Apr 13 Javascript
微信小程序实现瀑布流布局与无限加载的方法详解
May 12 Javascript
JavaScript原生实现观察者模式的示例
Dec 15 Javascript
跨域请求两种方法 jsonp和cors的实现
Nov 11 Javascript
微信小程序8种数据通信的方式小结
Feb 03 Javascript
vue使用swiper实现中间大两边小的轮播图效果
Nov 24 #Javascript
通过GASP让vue实现动态效果实例代码详解
Nov 24 #Javascript
JS控制只能输入数字并且最多允许小数点两位
Nov 24 #Javascript
解决Vue.js应用回退或刷新界面时提示用户保存修改问题
Nov 24 #Javascript
Egg Vue SSR 服务端渲染数据请求与asyncData
Nov 24 #Javascript
mpvue微信小程序开发之实现一个弹幕评论
Nov 24 #Javascript
node.js中Buffer缓冲器的原理与使用方法分析
Nov 23 #Javascript
You might like
PHP中改变图片的尺寸大小的代码
2011/07/17 PHP
PHP中使用Imagick读取pdf并生成png缩略图实例
2015/01/21 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
一个js拖拽的效果类和dom-drag.js浅析
2010/07/17 Javascript
DOM2非标准但却支持很好的几个属性小结
2012/01/21 Javascript
如何让div span等元素能响应键盘事件操作指南
2012/11/13 Javascript
js实现全屏漂浮广告移入光标停止移动
2013/12/02 Javascript
javascript基于HTML5 canvas制作画箭头组件
2014/06/25 Javascript
Javascript递归打印Document层次关系实例分析
2015/05/15 Javascript
jquery关于事件冒泡和事件委托的技巧及阻止与允许事件冒泡的三种实现方法
2015/11/27 Javascript
javascript轮播图算法
2016/10/21 Javascript
使用jQuery操作DOM的方法小结
2017/02/27 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
Node.js npm命令运行node.js脚本的方法
2018/10/10 Javascript
JavaScript实现单图片上传并预览功能
2019/09/30 Javascript
微信小程序动态添加和删除组件的现实
2020/02/28 Javascript
Node使用koa2实现一个简单JWT鉴权的方法
2021/01/26 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
[00:32]2018DOTA2亚洲邀请赛OpTic出场
2018/04/03 DOTA
[01:10:58]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
Python实现扫描局域网活动ip(扫描在线电脑)
2015/04/28 Python
解决pyinstaller打包pyqt5的问题
2019/01/08 Python
python中if及if-else如何使用
2020/06/02 Python
高尔夫球鞋、服装、手套和装备:FootJoy
2018/12/15 全球购物
碧欧泉Biotherm加拿大官方网站:法国高端护肤品牌
2019/10/18 全球购物
工厂厂长岗位职责
2013/11/08 职场文书
阿德的梦教学反思
2014/02/06 职场文书
学校节能减排倡议书
2014/05/16 职场文书
装饰公司活动策划方案
2014/08/23 职场文书
个人批评与自我批评材料
2014/10/17 职场文书
成功的商业计划书这样写才最靠谱
2019/07/12 职场文书
小学作文之描写天气
2019/08/15 职场文书
Django开发RESTful API实现增删改查(入门级)
2021/05/10 Python
Python OpenCV超详细讲解读取图像视频和网络摄像头
2022/04/02 Python
使用Redis实现分布式锁的方法
2022/06/16 Redis
详解Anyscript开发指南绕过typescript类型检查
2022/09/23 Javascript