我将提供一个更通用的解决方案,不使用 lodash 或其他外部依赖项
const traverse = function* (node, path = [])
{
if (Object (node) === node)
for (const [ key, value ] of Object.entries (node))
yield* traverse (value, [ ...path, key ])
else
yield [ path, node ]
}
我们可以使用for 循环轻松遍历我们的数据。请注意,生成器为原始对象中的每个值生成一个 path-value 对。 所有原始值都包含在输出中,这次不仅仅是字符串
// add a non-string value for demo
const myObject = {
...
d: 1
};
for (const [ path, value ] of traverse (myObject)) {
console.log ('path', path)
console.log ('value', value)
console.log ('---')
}
// path [ 'a' ]
// value myObject.a
// ---
// path [ 'b', 'ba' ]
// value myObject.b.ba
// ---
// path [ 'b', 'bb', '0' ]
// value myObject.b.bb[0]
// ---
// path [ 'c', '0', 'ca' ]
// value myObject.c[0].ca
// ---
// path [ 'd' ]
// value 1
// ---
如果我们愿意,我们可以使用 Array.from 收集所有对
Array.from (traverse (myObject))
// [ [ [ 'a' ], 'myObject.a' ]
// , [ [ 'b', 'ba' ], 'myObject.b.ba' ]
// , [ [ 'b', 'bb', '0' ], 'myObject.b.bb[0]' ]
// , [ [ 'c', '0', 'ca' ], 'myObject.c[0].ca' ]
// , [ [ 'd' ], 1 ]
// ]
您可能已经注意到,我将path 保留为一个数组,而不是使其成为. 分隔的字符串。没有必要把它变成一个字符串,以后再拆分它。
const lookup = (obj, [ key, ...path ]) =>
obj && key
? lookup (obj [key], path)
: obj
for (const [ path, value ] of traverse (myObject)) {
console.log ('path', path)
console.log ('value', value)
console.log ('lookup', lookup (myObject, path))
console.log ('---')
}
// path [ 'a' ]
// value myObject.a
// lookup myObject.a
// ---
// path [ 'b', 'ba' ]
// value myObject.b.ba
// lookup myObject.b.ba
// ---
// path [ 'b', 'bb', '0' ]
// value myObject.b.bb[0]
// lookup myObject.b.bb[0]
// ---
// path [ 'c', '0', 'ca' ]
// value myObject.c[0].ca
// lookup myObject.c[0].ca
// ---
// path [ 'd' ]
// value 1
// lookup 1
// ---