这是之前字节面试时的一道题,当时脑子比较混乱,但在面试官指引下还是写出了大部分,后面又仔细想了想,感觉还是得多写题。我们来看看吧
题目
const entry = [{id: '1',isOpen: true}, {id: '2',children: [{id: '21',children: [{id: '211',isOpen: false}, {id: '212',isOpen: false}]}]}, {id: '3',isOpen: false}]// 平铺,如果有isOpen属性则直接输出,如果没有则查看children里面有没有// 只要children里面有一个true,那么外层就是truelet output = {'1':true, '2':true, '21':true, '211':true, '212':false, '3':false}
思路:
(1)首先是先遍历这个树状数组的每一层,拿到 id 当 key,如果有 isOpen 属性,则直接把 isOpen 属性赋给 key,如果没有 则先 递归得到 children的遍历结果,并用 Object.assign合并res和递归的结果
没有isOpen属性的则被跳过了,因此我们把没有isOpen属性的单独考虑
(2)做到这里,有 isOpen 属性已经得到了 ,但是没有 isOpen 属性的我们则需要另外考虑,我的思路就是另外写一个judge函数来递归判断 其 children 内有没有 isOpen 是 等于 true的
function flatObj(arr) {let res = {}for (const item of arr) {let id = item.idlet isOpen = item.isOpenif (isOpen !== undefined) {res[id] = isOpen} else {// 没有isOpen则查找children,并且合并递归结果Object.assign(res, flatObj(item.children))// 没有isOpen单独考虑res[id] = judge(item.children)}// 分步打印看结果console.log(res);}return res}// 判断children内是否有isOpen=truefunction judge(arr){let flag = falsefor (const item of arr) {let isOpen = item.isOpenif (isOpen !== undefined) {if(isOpen){flag = true}} else {// 如果还是没有,则继续去children内找,最后都没有则返回falseflag = judge(item.children)}}return flag}console.log(flatObj(entry));
最后我们来看指向结果,由于直接看结果不明显,因此我们把它分步打印出来
由结果我们可以看出,3是被最后才加进去的,由于对象内部的key排列问题,3被排到了前面,但这不影响结果。
