在查阅 MDN 文档的时候看到这个例子:
如果数组为空且没有提供 initialValue,会抛出 TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供 initialValue, 或者有提供 initialValue 但是数组为空,那么此唯一值将被返回并且 callback 不会被执行。
提供初始值通常更安全,正如下面的例子,如果没有提供 initialValue,则可能有四种输出:
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );
// reduce() 没有初始值
[ { x: 2 }, { x: 22 }, { x: 42 } ].reduce( maxCallback ); // NaN
[ { x: 2 }, { x: 22 } ].reduce( maxCallback ); // 22
[ { x: 2 } ].reduce( maxCallback ); // { x: 2 }
[ ].reduce( maxCallback ); // TypeError
// map/reduce; 这是更好的方案,即使传入空数组或更大数组也可正常执行
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2, -Infinity );
这里面第一个数组的 reduce 为啥会返回 NaN 呢,求大佬解惑。 地址: https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/global_objects/array/reduce
1
bearice 2021-02-05 16:18:21 +08:00 1
Math.max(undefined,anything) == NaN
Math.max(NaN,anything) == NaN |
2
liuy1994g 2021-02-05 16:19:42 +08:00 1
isNaN(Math.max(undefined, 2)) === true
|
3
Austaras 2021-02-05 16:21:18 +08:00 1
maxCallback 返回的是数字,数字上没有 ‘x’ 这个属性
|
4
SakuraKuma 2021-02-05 16:21:19 +08:00 1
Math.max 返回的是 Number, 没有.x
|
5
yyfearth 2021-02-05 16:26:56 +08:00 2
reduce 有两个参赛 第一个是一个 function 就和你现在用的一样 但是有第二个参数就是初始值
如果初始值没给 那么第一个元素就是初始值 所以 [ { x: 2 }, { x: 22 }, { x: 42 } ].reduce( maxCallback ) 就是 [ { x: 22 }, { x: 42 } ].reduce( maxCallback, { x: 2 } ) 第一次运算 是 { x: 2 } 和 { x: 22 } 结果为 22 第二次运算 是 22 和 { x: 42 } 那么 (22).x 是 undefined 那么 Math.max(undefined, 42) 结果就是 NaN 这就是为什么正确的做法先做了一下 map 把 x 都取出来 然后在 reduce 不过我这样应该是更简单的做法 只不过这个 function 没有普遍性 其他地方可能没办法复用逻辑 [ { x: 22 }, { x: 42 } ].reduce( ( acc, cur ) => Math.max( acc, cur.x ), -Infinity) |
6
momocraft 2021-02-05 16:27:06 +08:00
从第 2 块的第 3 行向上看
当 acc 是 22 的时候 ,再和 {x:42} reduce 一次就得到 NaN |
7
teslayun OP 感谢楼上几位大佬解惑,明白了,reduce 里面的函数回调第三次执行的时候 maxCallback 返回的数字没有 X 属性:)
|
8
xngiser 2021-02-05 16:43:08 +08:00
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
第一次 acc: { x: 2 } cur: { x: 22 } acc=> 22 第二次 acc: 22 cur: { x: 42 } acc=> NaN |
9
SoloCompany 2021-02-05 19:13:26 +08:00 via iPhone
类型不匹配,要么先 map 再 reduce,要么 reduce 返回相同套娃结构体
|
10
KuroNekoFan 2021-02-05 21:51:21 +08:00 via iPhone
reduce 的 api 有点复杂,其实你弄个 forEach 也行的,而且比较好读,就是要多声明一个变量
|