如何以一种干净的方式遍历嵌套对象?我正在尝试在此结构的对象的第三级获取值:
const myObj = {
firstObj: {
nested: {
anotherNest: 'i want to get this value'
},
again: {
'i want this value ->': ':D'
}
}
}
显而易见的解决方案是三个嵌套的for循环:
for (const key1 of Object.keys(myObj))
for (const key2 of Object.keys(myObj[key1]))
for (const key3 of Object.keys(myObj[key1][key2]))
...
该解决方案根本不是干净的(并且不能缩放)。我该如何解决?
答案 0 :(得分:3)
您在这里要做的几乎是遍历对象第三级的值。您可以创建一个迭代器来为您执行此操作。生成器函数非常适合此操作,因为您可以轻松地递归使用它们。以下代码(在Typescript中)将使您轻松地做到这一点:
type NestedObjects <T> = {
[key: string]: NestedObjects <T> | T
}
/**
* Iterates through all values nested at n levels deep.
* Every iteration yields an array containing all keys looped through, in reverse.
* This means that the first entry will be the value at n levels, followed by keys at n-1, n-2, etc.
*
* Example:
* <pre>
* for (const x of NestedObjectIterator(a, 3)) ...
* </pre>
*
* is equivalent to three nested for loops:
* <pre>
* for (const x of Object.keys(a))
* for (const y of Object.keys(a[x]))
* for (const z of Object.keys(a[x][y])) ...
* </pre>
*/
function * NestedObjectIterator <T> (obj: NestedObjects<T>, levels: number, ...prevKeys: string[]): Iterable<[T, ...string[]]> {
for (const key of Object.keys(obj)) {
if (levels === 1) yield [obj[key] as T, key, ...prevKeys]
else if (obj[key]) yield * NestedObjectIterator(obj[key] as NestedObjects<T>, levels - 1, key, ...prevKeys)
}
}
相当于纯Javascript:
function * NestedObjectIterator (obj, levels, ...prevKeys) {
for (const key of Object.keys(obj)) {
if (levels === 1) yield [obj[key], key, ...prevKeys]
else if (obj[key]) yield * NestedObjectIterator(obj[key], levels - 1, key, ...prevKeys)
}
}
您现在可以像这样遍历对象:
const myObj = {
firstObj: {
nested: {
anotherNest: 'i want to get this value'
},
again: {
'i want this value ->': ':D'
}
}
}
for (const [value] of NestedObjectIterator(myObj, 3)) {
console.log(value)
}