编辑:如下面kennytm和调查自己后所指出的,根据ECMA spec,当确定两个对象是在自定义排序相等,JavaScript是不离开这两个要求对象以相同的顺序。 Chrome和Opera都是唯一选择非稳定排序的两种主流浏览器,但其他浏览器还包括Netscape 8,Kazehakaze,IceApe和其他一些浏览器。 Chromium团队已将此错误标记为“按预期工作”,因此不会“固定”。如果在值相等的情况下需要数组保持原始顺序,则需要使用一些额外的机制(如上面的机制)。当排序对象时,返回0
实际上是无意义的,所以不要打扰。或者使用支持稳定排序的库,如Underscore/Lodash。排序对象的阵列中的铬
我刚刚收到一份报告,说我写的一些代码正在破坏Chrome浏览器。我已经追踪到我用来排序对象数组的自定义方法。我真的很想把这称为一个错误,但我不确定它是什么。
在排序对象数组的所有其他浏览器中,如果两个对象解析为相同的值,则其更新数组中的顺序保持不变。在Chrome中,它们的顺序似乎是随机的。在Chrome和任何其他浏览器中运行下面的代码。你应该明白我的意思。
我有两个问题:
首先,我正确的假设,当您的自定义分类器返回0
这两个比较项目应保持其原有的顺序(我有一种感觉,我错了)。
其次,有没有什么好的方法来解决这个问题?我能想到的唯一方法是在排序之前向数组中的每个成员添加一个自动递增数字,然后在两个项目sort
将解析结果与相同的值进行比较时使用该值。换句话说,从未返回0
这里的示例代码:
var x = [
{'a':2,'b':1},
{'a':1,'b':2},
{'a':1,'b':3},
{'a':1,'b':4},
{'a':1,'b':5},
{'a':1,'b':6},
{'a':0,'b':7},
]
var customSort = function(a,b) {
if (a.a === b.a) return 0;
if (a.a > b.a) return 1;
return -1;
};
console.log("before sorting");
for (var i = 0; i < x.length; i++) {
console.log(x[i].b);
}
x.sort(customSort);
console.log("after sorting");
for (var i = 0; i < x.length; i++) {
console.log(x[i].b);
}
在所有其他的浏览器,我看到的是,只有第一构件和阵列的最后一个成员获得移动(我见7,2,3,4,5,6,1
),但在Chrome中,内部数字似乎是随机的。
[编辑]非常感谢大家回答。我认为'不一致'并不意味着它是一个错误。另外,我只想指出,我的b
财产只是一个例子。实际上,根据用户的输入,我在大约20个键的任何一个上排列了一些相对较宽的对象。即使跟踪用户上次排序的内容仍不能解决我所看到的随机性问题。我的解决方法可能是此变种的一个近似变体(新代码突出显示):
var x = [
{'a':2,'b':1},
{'a':1,'b':2},
{'a':1,'b':3},
{'a':1,'b':4},
{'a':1,'b':5},
{'a':1,'b':6},
{'a':0,'b':7},
];
var i;
var customSort = function(a,b) {
if (a.a === b.a) return a.customSortKey > b.customSortKey ? 1 : -1; /*NEW CODE*/
if (a.a > b.a) return 1;
return -1;
};
console.log("before sorting");
for (i = 0; i < x.length; i++) {console.log(x[i].b);}
for (i = 0; i < x.length; i++) { /*NEW CODE*/
x[i].customSortKey = i; /*NEW CODE*/
} /*NEW CODE*/
x.sort(customSort);
console.log("after sorting");
for (i = 0; i < x.length; i++) {console.log(x[i].b);}
[V8问题90:V8并不稳定的排序(HTTP://代码.google.com/p/v8/issues/detail?id = 90“V8 bug 90”) – lawnsea 2010-07-07 14:59:03