将属性添加到array.reduce()返回对象的顺序

时间:2019-05-21 02:35:40

标签: javascript arrays object ecmascript-6

有人可以解释为什么在array.reduce()函数的不同用法中最终输出是相同的吗?

在第一种情况下,样本数组直接减少,而在第二种示例中,样本数组先反转然后减少。

var array = [{
        "Id": "1",
        "Week": "2019-01-13"
    },
    {
        "Id": "2",
        "Week": "2019-01-20"
    },
    {
        "Id": "3",
        "Week": "2019-01-27"
    }
];

array.reduce(function (acc, curr) {
    acc[curr.Id] = curr.Week;
    console.log(acc);
    return acc;
}, {});

//Output
/*{ "1": "2019-01-13" }
{ "1": "2019-01-13", "2": "2019-01-20" }
{ "1": "2019-01-13", "2": "2019-01-20", "3": "2019-01-27" }*/

array.reverse().reduce(function (acc, curr) {
    acc[curr.Id] = curr.Week;
    console.log(acc);
    return acc;
}, {});
//Output 
/*{ "3": "2019-01-27" }
{ "2": "2019-01-20", "3": "2019-01-27" }
{ "1": "2019-01-13", "2": "2019-01-20", "3": "2019-01-27" }
*/

我希望输出显示为 {“ 3”:“ 2019-01-27”,“ 2”:“ 2019-01-20”,“ 1”:“ 2019-01-13”}。

如果我使用非数字键,则两种情况下的reduce函数输出均与预期的一样(以相同的顺序传递元素)。

1 个答案:

答案 0 :(得分:1)

正如注释中已经提到的, JS中不能保证对象道具顺序,这就是为什么要获得该输出的原因。如果您要处理问题,则需要使用Map作为reduce accumulator

  

Map对象保存键值对并记住原始值   键的插入顺序。

话虽如此,这里有一些示例代码可以更好地说明它:

var array = [{ "Id": "1", "Week": "2019-01-13" }, { "Id": "2", "Week": "2019-01-20" }, { "Id": "3", "Week": "2019-01-27" } ];

let r1 = array.reduce(function(acc, curr) {
  acc.set(curr.Id, curr.Week);
  return acc;
}, new Map());

let r2 = array.reverse().reduce(function(acc, curr) {
  acc.set(curr.Id, curr.Week);
  return acc;
}, new Map());

console.log('r1:')
r1.forEach(x => console.log(x))

console.log('r2:')
r2.forEach(x => console.log(x))

console.log('fromEntries:')
console.log(Object.fromEntries(r1))
console.log(Object.fromEntries(r2))

请注意,当我们循环浏览两个映射(r1r2)的条目时,顺序是如何不同的。但是还请注意,convert映射到对象文字时的顺序现在是相同的,因为不能保证JS prop顺序。