对具有空属性的对象进行排序会在 Firefox 和 Chrome 之间产生不同的结果

Sorting an object with null properties yields different results between Firefox and Chrome

我有一个对象数组,我正尝试对其应用 2 种排序。对 'name' 属性 进行简单的字母排序,然后对 'rank' 属性 进行排序,可以是数字或空值。具有 null 'rank' 的对象应排序到最终数组的末尾。

此代码在 Chrome、Safari 和 Edge 中按预期运行。然而,在 Firefox 中,它会颠倒所有具有空 'rank'.

的对象的字母顺序

JSFiddle:https://jsfiddle.net/6Lfu1z39/

代码:

const data = [
    {
    "name": "F",
    "rank": 2
    },{
    "name": "B",
    "rank": null
    },{
    "name": "A",
    "rank": 1
    },{
    "name": "E",
    "rank": null
    },{
    "name": "D",
    "rank": null
    },{
    "name": "C",
    "rank": 2
    }
]

const nameSort = (a, b) => {
    const nameA = a.name.toUpperCase();
    const nameB = b.name.toUpperCase();

    if (nameA < nameB) {
        return -1;
    } else if (nameA > nameB) {
        return 1;
    }
    return 0;
};

const rankSort = (a, b) => {
    if (a.rank === null) {
        return 1;
    } else if (b.rank === null) {
        return -1;
    }
    return 0;
}

console.log('name only', data.sort(nameSort));
console.log('name and rank', data.sort(nameSort).sort(rankSort));

哪个浏览器是正确的?或者,是否可以采取任何措施使浏览器之间保持一致?

看起来,您 return 用于比较的相同值的错误值。

例如 a.rank === null b.rank === null,你 return 1 但正确的值是在这种情况下,零到 return.

排序算法的实现取决于供应商,并且可以 return 不同的结果,具体取决于排序的顺序,例如从开始还是从结束。

要克服这个问题,您需要实现一个算法,该算法return对于相等的值为零。

const data = [{ name: "F", rank: 2 }, { name: "B", rank: null }, { name: "A", rank: 1 }, { name: "E", rank: null }, { name: "D", rank: null }, { name: "C", rank: 2 }]

const nameSort = (a, b) => {
    const nameA = a.name.toUpperCase();
    const nameB = b.name.toUpperCase();

    return nameA > nameB || -(nameA < nameB);
};

const rankSort = (a, b) => (a.rank === null) - (b.rank === null) 
        
    

console.log('name only', data.sort(nameSort));
console.log('name and rank', data.sort(nameSort).sort(rankSort));
.as-console-wrapper { max-height: 100% !important; top: 0; }

这是解决此问题的另一种方法。您可以结合使用 Array.prototype.sort()Array.prototype.filter() 方法来获得最终结果。首先,对名称 属性 应用字母排序。之后使用数组过滤的方法将所有的空 'rank' 属性 放在数组的末尾。

const data = [
  {
    name: 'F',
    rank: 2,
  },
  {
    name: 'B',
    rank: null,
  },
  {
    name: 'A',
    rank: 1,
  },
  {
    name: 'E',
    rank: null,
  },
  {
    name: 'D',
    rank: null,
  },
  {
    name: 'C',
    rank: 2,
  },
];

data.sort((x, y) => x.name.localeCompare(y.name));
console.log('name only', data);

const ret = [
  ...data.filter((x) => x.rank !== null),
  ...data.filter((x) => x.rank === null),
];
console.log('name and rank', ret);