为什么这种 Array.sort 行为在 Chrome 和 Node.js 中不同

Why is this Array.sort behaviour different in Chrome vs Node.js

问题

让我们制作一个基本列表并对其进行排序,以确保 2 始终排在列表的第一位。很简单吧?

[1, 2, 3].sort((a, b) => {
  if (a === 2) return -1;
  return 0;    
});

Chrome 结果:✓

[2, 1, 3]

节点结果:X

[1, 2, 3]

为了在 Node 中获得这种行为,你可以 - 很奇怪 - 查看 b 参数并将其设置为 return 1 如果它是 2:

[1, 2, 3].sort((a, b) => {
  if (b === 2) return 1;
  return 0;    
});

使用这个实现你会得到相反的结果; Chrome 将为 [1, 2, 3],节点将为 [2, 1, 3]。

问题

您对这种行为有合理的解释吗? 我的排序功能在概念上有缺陷吗?如果是这样,你会如何编写这种排序行为?

Do you have a logical explaination for this behaviour?

浏览器使用不同的排序方法。因此,他们可能会以不同的顺序使用不同的参数调用提供的回调。如果你的排序函数不一致,排序就不稳定。这将导致错误的排序顺序(对于不同的输入数组也总是如此,因此您的排序永远不会真正起作用)。

If so, how would you write this sorting behaviour?

确保这两个条件适用于每个可能的输入:

1) 两个相等的元素不应被排序:

  sort(a, a) === 0

2) 如果调用排序函数的顺序是倒序的,结果也是倒序的:

  sort(a, b) - sort(b, a) === 0

在你的情况下,两者都没有填满:

  sort(2, 2) // 1 -> wrong!
  sort(2, 3) - sort(3, 2) // 1 -> wrong!

要写出稳定的排序,得看a b:

  function(a, b) {
    if(a === 2 && b === 2)
      return 0;
    if(a === 2)
      return 1;
    if(b === 2)
      return -1;
    return 0;
  }

或者缩短:

  (a, b) => (a === 2) - (b === 2)