JavaScript嵌套对象数组的值求和与遍历问题
解决ES5环境下嵌套数组对象的weight求和与遍历问题
我明白你折腾了好几个小时找解决方案的痛苦,这个数组的结构确实有点棘手——既有直接包含weight属性的对象,又有嵌套了子对象的容器。既然是ES5环境,咱们用原生JS或者调整下lodash的用法就能搞定,下面一步步来:
先写一个通用辅助函数(核心)
不管是求和还是遍历,第一步都需要把所有嵌套的目标对象(就是那些带id、text、weight的对象)提取到一个扁平数组里。因为ES5没有Object.values(),咱们先写一个工具函数来获取对象的所有值:
// 获取对象的所有值(ES5兼容版) function getObjectValues(obj) { var values = []; for (var key in obj) { // 只处理自身属性,避免原型链上的属性 if (obj.hasOwnProperty(key)) { values.push(obj[key]); } } return values; } // 提取所有目标对象的函数 function getAllTargetItems(arr) { var result = []; arr.forEach(function(item) { // 判断当前元素是直接的目标对象(有weight属性),还是嵌套容器 if (typeof item.weight !== 'undefined') { result.push(item); } else { // 是容器的话,把里面的子对象都加入结果 var nestedItems = getObjectValues(item); result = result.concat(nestedItems); } }); return result; }
函数1:求和所有weight属性值
有了上面的辅助函数,求和就很简单了,用数组的reduce方法累加即可:
function sumAllWeights(answers) { var allItems = getAllTargetItems(answers); return allItems.reduce(function(total, item) { // 加个兜底,防止某些对象没有weight的情况 return total + (item.weight || 0); }, 0); // 初始值设为0 } // 调用示例 var totalWeight = sumAllWeights(answers); console.log(totalWeight); // 输出10(和你给出的3+2+1+2+1+1+0结果一致)
如果你想用lodash的话,之前的sumBy没成功是因为没先扁平化嵌套的容器,调整一下写法就行:
// lodash版本(ES5兼容) function sumAllWeightsWithLodash(answers) { var flatItems = _.flatMap(answers, function(item) { // 判断是否是嵌套容器:是纯对象且没有weight属性 return _.isPlainObject(item) && !_.has(item, 'weight') ? _.values(item) : [item]; }); return _.sumBy(flatItems, 'weight'); }
函数2:遍历所有目标元素
同样基于辅助函数,直接用forEach遍历提取后的数组即可,你可以在回调里做任何需要的处理:
function traverseAllItems(answers, callback) { var allItems = getAllTargetItems(answers); allItems.forEach(callback); } // 调用示例:打印每个对象的id、text和weight traverseAllItems(answers, function(item) { console.log('ID:', item.id, 'Text:', item.text, 'Weight:', item.weight); });
这样两个函数就完全独立,而且适配你给出的数组结构啦。
内容的提问来源于stack exchange,提问作者user990951
相关产品推荐
相关产品推荐

