如何从嵌套对象中按指定类型提取link字符串数组
需求
从给定的嵌套对象中,根据指定类型提取对应的link字符串数组。
源对象
const obj = { id: '01', options: {}, children: [ { id: '02', type: 'green', options: { link: 'http://some-page-023' }, children: [ { id: '03', type: 'black', options: {}, children: [], }, { id: '04', type: 'green', options: { link: 'http://some-page-044' }, children: [ { id: '05', type: 'white', options: {}, children: [], } ], } ], }, { id: '06', type: 'black', options: { link: 'http://some-page-258' }, children: [ { id: '07', type: 'green', options: { link: 'http://some-page-055' }, children: [], }, { id: '08', type: 'white', options: {}, children: [ { id: '09', type: 'green', options: { link: 'http://some-page-023' }, children: [], } ], } ], }, ] }
当前可正常运行的实现
const a = [] const getLinks = (data, ltype) => { if (data.children) { for( let el in data.children) { if (data.children[el].type === ltype) { a.push(data.children[el].options.link) } getLinks(data.children[el], ltype) } } return a } const result = getLinks(obj, 'green') console.dir(result, { depth: null })
运行结果
['http://some-page-023', 'http://some-page-044', 'http://some-page-055', 'http://some-page-023']
优化需求与问题尝试
需要优化实现,让数组在函数内部初始化并由函数直接返回。尝试的写法如下,但无法得到正确结果:
const getLinks = (data, ltype) => { const a = [] function recursiveFind(children, ltype) { if (data.children) { for (let el in data.children) { if (data.children[el].type === ltype) { a.push(data.children[el].options.link) } else { recursiveFind(data.children[el], ltype) } } } } recursiveFind(data, ltype) return a } const result = getLinks(obj, 'green') console.dir(result, { depth: null })
问题分析与正确优化实现
尝试的写法存在三个关键问题:
- 递归函数里错误引用外部的
data.children,而非传入的参数,导致始终处理根节点的子元素,无法深入嵌套层级 - 使用
else分支触发递归,会导致匹配类型的节点跳过子元素遍历,漏掉深层的匹配项 for...in遍历数组语义不够清晰,更适合对象遍历
正确的优化实现如下:
const getLinks = (data, ltype) => { const links = []; function recursiveFind(node) { // 检查当前节点是否匹配类型,存在link则收集 if (node.type === ltype && node.options?.link) { links.push(node.options.link); } // 递归处理所有子节点 if (node.children?.length) { node.children.forEach(child => recursiveFind(child)); } } recursiveFind(data); return links; } const result = getLinks(obj, 'green'); console.dir(result, { depth: null });
优化说明
- 数组
links在函数内部初始化,避免全局变量污染,多次调用函数不会互相干扰 - 递归函数接收当前节点作为参数,正确遍历每一层级的元素
- 先检查当前节点再递归子节点,不会遗漏任何匹配项
- 使用可选链
?.避免options或children不存在时抛出错误 - 用
forEach遍历数组,语义更贴合数组操作场景
运行后会得到和原实现一致的正确结果:
['http://some-page-023', 'http://some-page-044', 'http://some-page-055', 'http://some-page-023']
内容的提问来源于stack exchange,提问作者track_p54skate
相关产品推荐
相关产品推荐

