这是我参与更文挑战的第10天,活动详情查看: 更文挑战
问题背景
如何想起来这个问题的,主要是在给成员讲解数组reduce方法的时候想到的,想举个例子说明这个函数的特殊性。
Array.reduce()
- reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值。
- reduce() 方法在数组中从左到右工作。
- reduce() 方法不会减少原始数组。
- reduce() 方法接收一个函数 callback 作为累加器函数处理,数组中的每个值(从左到右)开始合并,最终为一个值。
语法
array.reduce(callback, initialValue)
参数
传给 reduce()和 reduceRight()的函数接收 4 个参数
- 总数(初始值/先前返回的值)
- 项目值
- 项目索引
- 数组本身
回调函数第一次执行时,总数 和 项目值可以是一个值,如果 initialValue 在调用 reduce() 时被提供,那么第一个 总数 等于 initialValue ,并且 项目值 等于数组中的第一个值;如果 initialValue 未被提供,那么 总数 等于数组中的第一个值,项目值 等于数组中的第二个值。
数组迭代方法对每个数组项进行操作:这个函数每次迭代执行的返回值都会作为下一次迭代执行函数的第一个参数。
讲到函数每次迭代返回的任何值都会作为第一个参数自动传给下一项的好处,就引出下面的问题。
二叉树遍历计算求值问题
要求:不借助变量去计算所有节点累加值
var a = [{
count: 1,
name: 'a',
children: [{
count: 2,
name: 'b',
children: [{
count: 3,
name: 'c'
},
{
count: 4,
name: 'd'
}]
},
{
count: 5,
name: 'e',
children: [{
count: 6,
name: 'f'
},
{
count: 7,
name: 'g'
}]
}]
}]
解决思路
不借助变量计算数据的话,那就只有可以自主进行数值计算。正好可以借用这个方法的特性实现,然后一行代码的情况就需要考虑带自调用,然后具有一定的链式效果。这里就采用立即执行表达式 + reduce方法的特性。
实现方法
var a = [{
count: 1,
name: 'a',
children: [{
count: 2,
name: 'b',
children: [{
count: 3,
name: 'c'
},
{
count: 4,
name: 'd'
}]
},
{
count: 5,
name: 'e',
children: [{
count: 6,
name: 'f'
},
{
count: 7,
name: 'g'
}]
}]
}]
console.log((function countF(a) {
return a.reduce(function(x, y) {
if (y.children) {
// 存在子节点的情况下
return x + y.count + countF(y.children)
} else {
// 不存在子节点的情况下
return x + y.count
}
},
0)
})(a))
返回结果