Reduce方法不清晰

3

于是,我开始尝试使用reduce()方法,并且我意识到我可以将一个对象作为该方法的第一个元素传入。我看到了一些例子,这是其中之一。

const arr = ['y', 'n', 'y', 'y', 'n'];

let test = arr2.reduce((sum, val) => {
    sum[val] = (sum[val] || 0) + 1;
    console.log('sum of val', sum[val], 'value', val)
    return sum;
}, {})

我加了一个控制台日志,以便看到发生了什么,但我无法弄清楚。这个方法是如何知道的?它如何将该值(即n或y)添加到对象中,并跟随它在数组中添加相同元素存在的总和。例如,当数组中有20个y时,如何使该总和变为{y: 20}。
我对此感到困惑,起初它似乎很简单,但我想它并不简单。

但是当我console.log那个sum[val]时,它会给我一个被求和元素的值。所以基本上这意味着我说0 = (0 || 0) + 1,那么y或n在哪里? - Dario K
请查看下面的答案 - CherryDT
这个问题是关于.reduce()还是sum[val] = (sum[val] || 0) + 1的工作原理? - Andreas
2个回答

3
它并不会自动“知道”,你需要在这里操作:sum[val] = (sum[val] || 0) + 1; 在第一个迭代中,sum 是空对象,然后它是从上一次迭代返回的对象(由于return sum;),因此val是当前值('y''n')。因此,在第一个迭代中,sum将是{},而val将是'y'。然后,这一行会设置sum['y'] = 1,因为它实际上执行了sum['y'] = (sum['y'] || 0) + 1,而此时sum['y']undefined,因此你将得到(undefined || 0) + 1,等于0 + 1,也就是1。同样的操作会出现在下一个值'n'上。
第三次操作时,sum['y'] 已经是前面的1,所以表达式就变成了 (1 || 0) + 1 ,即1 + 1,得到2,所以你会得到sum['y'] = 2。以此类推。 可参考这个调试器的演示:https://recordit.co/FVkXjW1b5y

所以sum变成了一个对象(并且永久地保持为一个对象),这就是它能够工作的原因? - Dario K
1
“sum” 从一开始就是一个对象,因为你将它传递给了 .reduce()(这已经在你的问题中提到:“我可以将一个对象作为第一个元素传递”)。 - Andreas
x.reduce(..., {}) <== 这里的 {} 是一个对象!你需要自己将其传入函数中。 - CherryDT

2

.reduce()接受两个参数:

  • 回调函数
  • 初始值(可选)

在你的情况下,空对象字面量{}是初始值。如果提供了初始值,则将其作为第一个参数传递给回调函数

.reduce()的回调函数的第二个参数是.reduce()所调用的数组的当前元素。在第一次迭代中,valarr数组中的第一个元素,即'y'

sum[val] = (sum[val] || 0) + 1;

在每次迭代中,上述语句将把val的值作为键添加到sum对象(初始值),如果sum[val]未定义,则其值为0 + 1,如果sum[val]已定义,则其值为sum[val] + 1
您的代码执行方式如下:
当第一次调用回调函数时,sum{}val'y'。由于sum[val]sum['y']undefined,所以'y'被添加为sum中的键,并且其值为1。当回调函数第二次被调用时,同样的事情发生了。经过2次调用后,sum看起来像{ y: 1, n: 1 }
在第三次调用中,由于sum[val]等于1,因此先前添加的键y被覆盖为sum[val] + 1,其计算结果为1 + 1。因此,在第三次调用之后,sum看起来像{ y: 2, n: 1 }。在随后的回调函数调用中,同样的事情发生。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接