对象的递归遍历

188 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

在开始对象的遍历之前,我们先了解下几个概念。

for...in 循环不仅可以遍历数字键名,还会遍历原型上的值和手动添加的值。

hasOwnProperty:自定义的属性而不是原型链的属性。

reduce的使用,如果要使用到设置的初始值,记得要return prev。

Object.values返回的是对象的值组成的数组。

typeof判断类型值的时候,null会显示为‘object’;所以可以用 Object.prototype.toString.call这个方法,如果是null,会得到'[object Null]'。如果是Object,会得到'[object Object]'

[3,4,5].reduce((prev,next)=>{prev.push(next+8);return prev},[])

这个时候输出[11,12,13]

看如下题目:

const arr = [
    {
        name:'qiangwei',
        age:18,
        obj:{
            name1:'mike',
            age2:16,
            colors:{
                a:'red',
                b:'yellow',
                c:['pink','yellow']
            }
        },
         nums:[1,2,3]
    },
    new Date()
]

需要输出结果:
qiangwei,18,mike,16,red,yellow,pink,yellow,1,2,3,
Mon Apr 11 2022 18:05:57 GMT+0800 (中国标准时间)

分析输出结果:就是取数组中的每一项,遍历,如果那一项的值是数组或者对象,那就继续遍历,最后得到的是这个数组中所有值的拼接的一个字符串。

代码如下

let res =''
function itemvalue(arr) {
    if(Object.prototype.toString.call(arr).slice(8,-1).toLocaleLowerCase() === 'object'){
        Object.values(arr).forEach(item=>{
            itemvalue(item)
        })
    }else if(Array.isArray(arr)){
        arr.forEach(item=>{
            itemvalue(item)
        })
    }else{
        res += arr+ ','
    }
}

while(arr.length>0){
    itemvalue(arr.shift())
}
console.log(res.slice(0,-1))

可以看到还有重复的地方,接下来改版了一下。

function itemvalue(arr) {
    if(Object.prototype.toString.call(arr).slice(8,-1).toLocaleLowerCase() === 'object'){
        return   handleItem(Object.values(arr) )
    }else if(Array.isArray(arr)){
        return   handleItem(arr)
    }else{
      return arr
    }
} 
function handleItem(arr) {
    return  arr.reduce((prev,next)=>{
            prev.push(itemvalue(next))
            return prev
    },[]).join(',')
}

let jieguo = arr.reduce((prev,next)=>{
    return prev + itemvalue(next)  + ','
},'') 
console.log(jieguo.slice(0,-1))

看这个代码还有点冗余,应该是还可以再改进,于是又想了一下,然后最终的代码如下。

 const res = []
const isObject = data => Object.prototype.toString.call(data).slice(8,-1) === 'Object';
const transformdata = (data) => {
    if(Array.isArray(data) || isObject(data)) {
        data = Array.isArray(data) ? data : Object.values(data);
        const start = () => {
          const val = data.shift()
            if(val){
              transformdata(val) 
              start()
            }
        }
        start()
    }else {
        res.push(data)
    }
}
const flatData = data => {
    const start = () => {
        const val = data.shift()
        if(val){
          transformdata(val) 
          start()
        }
    }
    start()
}

flatData(arr);
console.log(res.join(','))