无聊逛github,需求是统计数组中元素出现的个数,使用reduce()可以很轻松实现,我的写法:
const countOccurrences = (arr) => arr.reduce((prev, cur) => {
if (cur in prev) {
++prev[cur]
} else {
prev[cur] = 1
}
return prev
}, {})
大神的写法:
const countOccurrences = (arr) => arr.reduce((prev, curr) => ((prev[curr] = ++prev[curr] || 1), prev), {});
简单介绍一下 || 或逻辑运算符
-
当参与运算的任意一个参数为true时,返回true,否则返回false;
-
console.log(true || false) // true console.log(false || true) // true console.log(true || true) // true console.log(false || false) // false -
那么如果给定多个参数,例如 1 || 2 || 3这种情况呢?直接 show code
-
console.log(1 || 2 || 3) // 1 console.log(66 || 2 || 3) // 66 console.log(1 || 0 || 3) // 1 console.log(null || null || 3) // 3 console.log(null || undefined || 0) // 0 console.log(null || 0 || undefined) // undefined -
发现如果结果为true,那么返回第一个真值;如果结果为false,那么返回最后一个值
回过头看代码,(prev[curr] = ++prev[curr] || 1) ,这段现在就很好理解了,但是主要让我疑惑的是,reduce()方法中prev参数是上一次调用回调的返回值,可是这段代码并没有看到return字样,这是怎么回事?难道是逗号?我的印象中,的确依稀记得是存在一个逗号运算符的,查阅了一下,果然没错。
逗号运算符
对它的每个操作数从左到右求值,并返回最后一个操作数的值
直接看代码:
let a = 10
let b = 12
let c = 15
let d
d = (a, b++, c++, 100)
console.log(a, b, c, d) // 10 13 16 100
现在已经大致有了解了,突然想到大四时期刚出去找实习面试的时候,笔试过这么一道题,如今突然茅塞顿开:
var i = j = 0, k = 0;
for(i, j; i < 10, j < 6; i++, j++) {
k = i + j;
}
console.log(k); // 10
当初天真以为循环结束的条件是i<10 , j<6中,小的那一项,即j>=6时跳出循环,所以蒙对了结果是10。如今看来,这里其实也是应用了逗号运算符,返回最后一项操作数的值,看下面的例子:
var i = j = 0, k = 0;
for(i, j; i < 6, j < 10; i++, j++) {
k = i + j;
}
console.log(k);
如果按照我之前的想法,那么调换值的顺序是没有影响的,可是结果输出为18,这也充分说明了的确是逗号运算符搞的鬼,k = 9 + 9 =18,当j=10时,跳出循环。
总结
再次回头看一下我的写法与大神的写法,其实都已经return prev,不过后者的写法看起来更简洁一些,由于本人才疏学浅,第一时间没有反应过来,今天也算是又收获了一个知识点。