为了账号安全,请及时绑定邮箱和手机立即绑定

Javascript中的array.reduce的问题及一个奇怪的抛出异常

Javascript中的array.reduce的问题及一个奇怪的抛出异常

天涯尽头无女友 2018-09-18 09:13:43
今天看到javascript的函数式编程的一篇文章,讲的是用reduce这个函数统计一个字符串中各字母出现的次数,代码如下:`var res = str.split('').reduce((pre, cur) => (pre[cur]++ || (pre[cur] = 1), pre), {})`然后我不知道上式中箭头函数的右边部分中的pre是什么意思,箭头函数右边不就是要返回的表达式吗,为什么上面上面的式子里面还多了个pre?然后我试着改写了一下:var res = str.split('')             .reduce(function(pre,cur){             console.log(pre) ;                          console.log(cur) ;             if( pre[cur] === 1)              {               pre[cur]++;              } else                pre[cur] = 1;             }, {});结果报错为:if( pre[cur] === 1)        ^ TypeError: Cannot read property 'd' of undefined为什么会报这样的错?谁能回答下这两个问题吗??感激不尽。百度谷歌了好久都找不到答案。。
查看完整描述

1 回答

?
胡子哥哥

TA贡献1825条经验 获得超6个赞

先改写一下,让你看得清楚些。

const str = 'ddd'const initialVal = {}let res = str.split('').reduce((pre, cur) => (pre[cur]++ || (pre[cur] = 1), pre), initialVal)

语法上的confusion

可以繁写为:

(pre, cur) => {  return pre[cur]++ || (pre[cur] = 1), pre}

形如 return 1, 3, 4 总是返回最后一个合法的值。

这里用这种偏门写法主要是为了能在一行中写完,使其既执行语句,还能返回值pre,供给下一次遍历消费。

算是片面追求短小。

加了注释的ES5写法

var str = 'ddd';// cache 是 reduce 函数进行累加操作时候的初始值。// 在这里,它主要用来缓存字符串中出现的字符和它们的出现次数。
// 遍历结束后,它的结构可能是 { d: 3 } 。var cache = {};var res = str.split('').reduce(function (pre, cur) {  
// pre 是一个 plain Object, 初始值为 cache ,可能形如 { d: 1 }。
  // 而 cur 是当前遍历到的字符,可能为 d。
  var cachedTimes = pre[cur]; // 所以这一步是在向buffer(缓存)中询问,是否已经缓存过 d,并且得到它的次数。

  if (cachedTimes) { 
    pre[cur] += 1; // 如果有值,说明已经缓存过,加上这次访问,其次数应该 + 1
  } else {
    pre[cur] = 1; // 如果为undefined,说明没有缓存过,在缓存中注册一下,次数为1
  }  return pre; // 把修改后的 pre 传给下一次遍历消费。}, cache);

在js中,使用cache表来缓存遍历次数是一个常见的优化办法。因为js中访问属性是很快的。

你改写的函数的错误之处

额,其实讲到这里你应该很明白了。然而你的reduce的回调函数体中并没有返回累计结果,传给下一次遍历。所以第二次遍历时,preundefined
你的str中第二个字符估计是dundefined.d当然报错啦。


PS 这种写法会更优雅吗?


查看完整回答
反对 回复 2018-10-21
  • 1 回答
  • 0 关注
  • 825 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信