你avatars
不是一个数组,它只是一个对象:
avatars = {};
所以它的元素没有定义的顺序:
未指定枚举属性的机制和顺序(第一个算法中的步骤 6.a,第二个算法中的步骤 7.a)。
和15.2.3.7(和15.2.3.14):
如果实现为 for-in 语句定义了特定的枚举顺序,则必须使用相同的枚举顺序来对该算法的步骤 3 中的列表元素进行排序。
您还可以查看第 8.6 节,看看是否有提及对象中属性的顺序。对象属性排序的唯一要求是,如果实现在任何地方定义了一个顺序,那么它必须在任何地方使用相同的排序,但这是一个很大的if。大多数实现可能对对象的键使用插入顺序,但我找不到任何需要它们的东西(如果有人能指出规范中定义对象键的任何特定顺序的任何内容,我将不胜感激)。
也就是说,UnderscoresortBy
基本上是一个Schwartzian Transform,结合了标准的 JavaScriptsort
和 Underscorepluck
来解开 Schwartzian Transform 备忘录包装器;pluck
返回一个数组,所以sortBy
也返回一个数组。因此,您的最终_.keys(avatars)
调用实际上是调用_.keys
一个数组;数组的键(AKA 可枚举属性)是数组的索引,它们是从零开始的连续整数。
您使用了错误的数据结构。如果您需要一个稀疏数组但还需要像数组一样操作它(即对其进行排序),那么您应该将索引放在对象内并使用普通数组而pluck
不是keys
:
var avatars = [
{idx: 102, userInfo: {buddy_name: 'Avatar102', is_online: 1}},
{idx: 100, userInfo: {buddy_name: 'Avatar100', is_online: 1}},
{idx: 101, userInfo: {buddy_name: 'Avatar101', is_online: 1}}
];
console.log(_(avatars).pluck('idx'));
avatars = _(avatars).sortBy(function(avatar) {
return avatar.userInfo.buddy_name.toLowerCase();
});
console.log(_(avatars).pluck('idx'));
演示:http: //jsfiddle.net/ambiguous/UCWL2/
如果您还需要快速访问,idx
那么您可以设置一个并行对象以进行直接idx
访问:
var avatars_by_idx = { };
for(var i = 0; i < avatars.length; ++i)
avatars_by_idx[avatars[i].idx] = avatars[i];
然后avatars_by_idx
提供您正在寻找的直接访问。当然,你必须保持avatars
和avatars_by_idx
同步,但如果你把它们都隐藏在一个对象后面,那并不是很困难。