写node过程中遇到这么一个问题,要根据一个字符串str="userInfo.uname.firstName"来判断一个前端通过body对象传参是否缺少必传参数,例如前端通过body传参如下:
{
userInfo: {
uname: {
firstName: 'Wu',
lastName: 'Dan'
},
age: 28
}
}
首先想到的是通过把 str 分割成数组 [ 'userInfo', 'uname', 'firstName' ],然后通过递归依次读取 body['userInfo']['uname']['firstName'] 的方式来判断有没有缺少 firstName 属性,查询过程中突然发现 reduce 这个冷门的 js 方法可能可以简化这个过程。
首先来了解一下 reduce 方法,官方给出的解释:
定义和用法
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce() 可以作为一个高阶函数,用于函数的 compose。
注意: reduce() 对于空数组是不会执行回调函数的。
语法
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
参数
参数 | 描述 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
function(total,currentValue, index,arr) | 必需。用于执行每个数组元素的函数。 函数参数:
| ||||||||||
initialValue | 可选。传递给函数的初始值 |
可以看出官方推荐的用法是使用这个累加器可以方便的计算一个数组元素的和,通过 return 可以把每次迭代的值返回给total作为下一次的初始值,如果我们 return 一个对象的话,不就可以依次读取多层嵌套的对象的属性了吗?
上代码:
// 现在有一个需要判断的字符串 'userInfo.uname.firstName',以及一个已有的对象 body{}
let str = 'userInfo.uname.firstName'
if(str.indexOf('.')){
let attrArr = str.split('.')
// prev 表示初始值或上一次 return 的值, cur 表示当前迭代器里的元素,从左到右依次迭代
attrArr.reduce((prev, cur) => {
// 如果 对象[属性] 存在,那么返回前一次 对象[属性],相当于往嵌套走了一层
if(!!prev[cur]){
return prev[cur]
}else{
throw new Error(cur + '不存在')
}
}, body) // 这里的 body 就是需要判断的对象
}
可以判断出 body 下的 userInfo uname firstName 任何一个嵌套层级缺少属性都会抛出错误.