You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript多字段排序结果多次不一致的原因探究

原生JavaScript toSorted多次排序结果不一致的原因

问题场景

使用JavaScript原生toSorted方法对数组按date和createdAt字段降序排序时,同一数组多次排序得到的结果顺序不同,不符合“相同输入应输出一致排序结果”的预期。

代码示例

const arr = [
    {"id": 0, 
     "date": new Date("2023-06-02T00:00:00.000Z"), 
     "createdAt": new Date("2023-06-05T01:48:37.586Z")
    },
    {
        "id": 1,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T01:31:35.901Z"),
    },
    {
        "id": 2,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T17:19:14.733Z"),
    },
    {
        "id": 3,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:10:26.454Z"),
    },
    {
        "id": 4,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:11:53.192Z"),
    },
    {
        "id": 5,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:13:13.879Z"),
    },
    {
        "id": 6,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:15:46.841Z"),
    },
    {
        "id": 7,
        "date": new Date("2023-06-03T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:16:45.006Z"),
    },
    {
        "id": 8,
        "date": new Date("2023-06-04T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T17:21:19.906Z"),
    },
    {
        "id": 9,
        "date": new Date("2023-06-04T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:01:39.286Z"),
    },
    {
        "id": 10,
        "date": new Date("2023-06-04T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:09:48.776Z"),
    },
    {
        "id": 11,
        "date": new Date("2023-06-04T00:00:00.000Z"),
        "createdAt": new Date("2023-06-04T21:27:45.701Z"),
    }
]

function sortItems(items) {
  return items.toSorted((a, b) => {
    // do comparison
    if (a.date > b.date) {
      return -1
    } else if (a < b.date) {
      return 1
    } else {
      if (a.createdAt > b.createdAt) {
        return -1
      } else if (b.createdAt < b.createdAt) {
        return 1
      } else {
        return 0
      }
    }
  })
}

const sort_1 = sortItems(arr)
console.log(sort_1)
const sort_2 = sortItems(sort_1)
console.log(sort_2)

问题原因

你的排序比较函数存在两处逻辑错误,导致排序逻辑失效,进而引发结果不稳定:

  1. a < b.date的错误比较:此处应该是a.date < b.date,你错误地将整个对象a和b.date进行比较,对象与Date类型的比较会得到不可预期的结果,导致date字段的比较逻辑混乱。
  2. b.createdAt < b.createdAt的无效判断:这是明显的笔误,应该是a.createdAt < b.createdAt,当前写法中左右都是b.createdAt,判断永远为false,导致date相同时,createdAt字段的比较逻辑完全失效。

当比较函数无法正确区分元素的顺序时,即使使用稳定排序算法(ES2019之后,toSorted是稳定排序),也会因为逻辑错误导致元素的相对位置无法被正确约束,多次排序时就会出现结果不一致的情况。

修复方案

修正比较逻辑的版本

function sortItems(items) {
  return items.toSorted((a, b) => {
    // 先按date降序比较
    if (a.date > b.date) {
      return -1;
    } else if (a.date < b.date) {
      return 1;
    } else {
      // date相同时按createdAt降序比较
      if (a.createdAt > b.createdAt) {
        return -1;
      } else if (a.createdAt < b.createdAt) {
        return 1;
      } else {
        return 0;
      }
    }
  });
}

简化版本(利用时间戳相减)

可以直接使用Date对象的getTime()方法获取时间戳,通过数值相减来简化比较逻辑,代码更简洁且不易出错:

function sortItems(items) {
  return items.toSorted((a, b) => {
    // date降序,date相同则createdAt降序
    return b.date.getTime() - a.date.getTime() || b.createdAt.getTime() - a.createdAt.getTime();
  });
}

修复后,多次排序同一数组会得到完全一致的结果,符合预期的降序排序逻辑。

内容的提问来源于stack exchange,提问作者Jamie Marshall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:00:00