猿问

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

今天看到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

为什么会报这样的错?
谁能回答下这两个问题吗??感激不尽。百度谷歌了好久都找不到答案。。


天涯尽头无女友
浏览 832回答 1
1回答

胡子哥哥

先改写一下,让你看得清楚些。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的回调函数体中并没有返回累计结果,传给下一次遍历。所以第二次遍历时,pre为undefined。你的str中第二个字符估计是d,undefined.d当然报错啦。PS 这种写法会更优雅吗?
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答