请教一个 reduce 方法的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
lebcvu
V2EX    Javascript

请教一个 reduce 方法的问题

  •  
  •   lebcvu 2021-02-05 16:14:44 +08:00 2720 次点击
    这是一个创建于 1784 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在查阅 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

    10 条回复    2021-02-05 21:51:21 +08:00
    bearice
        1
    bearice  
       2021-02-05 16:18:21 +08:00   1
    Math.max(undefined,anything) == NaN
    Math.max(NaN,anything) == NaN
    liuy1994g
        2
    liuy1994g  
       2021-02-05 16:19:42 +08:00   1
    isNaN(Math.max(undefined, 2)) === true
    Austaras
        3
    Austaras  
       2021-02-05 16:21:18 +08:00   1
    maxCallback 返回的是数字,数字上没有 ‘x’ 这个属性
    SakuraKuma
        4
    SakuraKuma  
       2021-02-05 16:21:19 +08:00   1
    Math.max 返回的是 Number, 没有.x
    yyfearth
        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)
    momocraft
        6
    momocraft  
       2021-02-05 16:27:06 +08:00
    从第 2 块的第 3 行向上看
    当 acc 是 22 的时候 ,再和 {x:42} reduce 一次就得到 NaN
    lebcvu
        7
    lebcvu  
    OP
       2021-02-05 16:27:33 +08:00
    感谢楼上几位大佬解惑,明白了,reduce 里面的函数回调第三次执行的时候 maxCallback 返回的数字没有 X 属性:)
    user4201
        8
    user4201  
       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
    SoloCompany
        9
    SoloCompany  
       2021-02-05 19:13:26 +08:00 via iPhone
    类型不匹配,要么先 map 再 reduce,要么 reduce 返回相同套娃结构体
    KuroNekoFan
        10
    KuroNekoFan  
       2021-02-05 21:51:21 +08:00 via iPhone
    reduce 的 api 有点复杂,其实你弄个 forEach 也行的,而且比较好读,就是要多声明一个变量
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5387 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 06:41 PVG 14:41 LAX 22:41 JFK 01:41
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86