IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 谈谈JavaScript对数组嵌套对象排序的sort方法和reverse方法 -> 正文阅读

[JavaScript知识库]谈谈JavaScript对数组嵌套对象排序的sort方法和reverse方法

最近在写个人博客网站,遇到了一个数组嵌套对象排序的问题,在解决过程中遇到了一些坑。在此详细说一下,以免后来人踩坑!

需求描述

现有简化后的数据内容如下:

let data = [
    {ArtId: 82, ArtName: "关于JavaScript处理时间戳转日期字符串与日期字符串转时间戳的函数", Date: 1630937933, State: 1,},
    {ArtId: 83, ArtName: "在manjaro下安装安卓投屏软件scrcpy详细过程", Date: 1630937929, State: 1},
    {ArtId: 84, ArtName: "学习GoFrame框架,从头开始一步步搭建个人博客WEB应用(中)", Date: 1630937925, State: 1},
    {ArtId: 80, ArtName: "关于JavaScript存、取Cookie的函数", Date: 1630937921, State: 1}
]

现在需求是点击“标题”按钮,那么将data按ArtName升序排列,再点击一次倒序排列,再点一次还原到原来的顺序。
另外3个字段也是如此:点击“日期”按钮,按Date排序;点击“状态”按钮,按State排序;点击“ID”按钮,按“ArtId”排序。

分析需求

这里需要用到2个数组方法,一个是sort,一个是reverse。
使用方法相同,sort是升序排列,reverse是倒序排列。下面我重点讲一下sort:
sort的调用方式是data.sort(function(key))。
这个funtion必须有一个参数,它必须是data数组中的键;
该函数会根据参数key提取sort函数传进来的2个元素的相关值:2个元素比较后返回正数那么做升序处理;返回0那么位置不变;返回负数那么做降序处理。
现在需要写一个可以同时比较数字、字符串以及异常情况的比较函数。

解决过程

首先写一个最简单的比较数字的函数,这个很简单,内容如下:

function compare(key) {
    return function (a, b) {
        let c = a[key]-b[key];
        return c > 0 ? 1 : c === 0 ? 0 : -1;
    }
}

这是一个闭包函数,key是数组中对象的键,a和b代表的是sort传进来的2个数组元素。

测试比较函数

这个简单,按f12打开控制台,把let data那段贴进去回车,然后把function compare贴进去回车,再执行data.sort(compare("Date"));
结果如下:
在这里插入图片描述
请注意,我执行了3次sort,每次结果都一致。
现在再来看看reverse,让我们执行3次data.reverse,看看是什么结果!
在这里插入图片描述

发现reverse的问题

是不是非常惊奇!!!
sort方法对数组排序,同样的参数无论执行多少次结果都一致!!
reverse方法对数组排序,同样的参数执行多次结果不一致!!!
请大家记住这个坑!!!太坑爹了,也没法看到reverse的源码,不知道为啥会这样,我们能做的就是不用reverse方法!

解决不能用reverse的问题

那么如何只用sort达到既可正向排序又可反向排序呢??
请看下面的代码:

function compare(key,flag=1) {
    flag = flag === 1 ? 1 : -1;
    return function (a, b) {
        let c = a[key]-b[key];
        return flag*(c > 0 ? 1 : c === 0 ? 0 : -1);
    }
}

加一个标志位参数,若没传第二个参数,那么是正向排序,如果传了第二个参数(无论第二个参数是啥)那么就逆向排序。
至于为啥写flag = flag === 1 ? 1 : -1;这句代码,这是防止传参不合规。

最终解决方案

哎,写累了,麻溜贴最终代码,懂的自然懂,不懂的复制粘贴直接用吧!

// 排序函数,可处理数字、undefined、NaN
function compare(key, flag = 1) {
    flag = flag === 1 ? 1 : -1;
    return function (a, b) {
        if (typeof a[key] === "number" && typeof b[key] === "number") {  // 比较双方都是数字,那么根据数字大小作比较
            let c = a[key] - b[key];
            return flag * (c > 0 ? 1 : c === 0 ? 0 : -1);
        }
        if (typeof a[key] === "undefined" || Number.isNaN(a[key])) {  // 判断a是未定义或NaN么?
            if (typeof b[key] === "undefined" || Number.isNaN(b[key])) {  // 判断b也是未定义或NaN么?
                return 0;  // a和b都是异常值,那么返回0
            } else {
                return -flag;  // a异常,b不异常时,当成a小于b处理
            }
        }
        if (typeof b[key] === "undefined" || Number.isNaN(b[key])) {
            return flag;  // b异常,a不异常时,当成a大于b处理
        }
        a = a[key].toString();  // a既不是数字、也不是异常,那么转成字符串进行后面的比较
        b = b[key].toString();  // b既不是数字、也不是异常,那么转成字符串进行后面的比较
        return flag * (a > b ? 1 : a === b ? 0 : -1);  // 两个字符串可以直接比较大小
    }
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 10:37:59  更:2021-09-08 10:39:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:39:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码