recorrer un objeto (árbol) de forma recursiva
¿Hay alguna manera (en jQuery o JavaScript) de recorrer cada objeto y sus hijos y nietos, etc.?
Si es así... ¿puedo leer también su nombre?
Ejemplo:
foo :{
bar:'',
child:{
grand:{
greatgrand: {
//and so on
}
}
}
}
entonces el bucle debería hacer algo como esto...
loop start
if(nameof == 'child'){
//do something
}
if(nameof == 'bar'){
//do something
}
if(nameof =='grand'){
//do something
}
loop end
Estás buscando el for...in
bucle:
for (var key in foo)
{
if (key == "child")
// do something...
}
Tenga en cuenta que for...in
los bucles iterarán sobre cualquier propiedad enumerable, incluidas aquellas que se agregan al prototipo de un objeto. Para evitar actuar sobre estas propiedades, puede usar el hasOwnProperty
método para verificar si la propiedad pertenece solo a ese objeto:
for (var key in foo)
{
if (!foo.hasOwnProperty(key))
continue; // skip this property
if (key == "child")
// do something...
}
Realizar el bucle de forma recursiva puede ser tan sencillo como escribir una función recursiva:
// This function handles arrays and objects
function eachRecursive(obj)
{
for (var k in obj)
{
if (typeof obj[k] == "object" && obj[k] !== null)
eachRecursive(obj[k]);
else
// do something...
}
}
Puede tener una función recursiva de bucle de objetos con una función de ejecución de propiedad propExec
incorporada.
function loopThroughObjRecurs (obj, propExec) {
for (var k in obj) {
if (typeof obj[k] === 'object' && obj[k] !== null) {
loopThroughObjRecurs(obj[k], propExec)
} else if (obj.hasOwnProperty(k)) {
propExec(k, obj[k])
}
}
}
Prueba aquí:
// I use the foo object of the OP
var foo = {
bar:'a',
child:{
b: 'b',
grand:{
greatgrand: {
c:'c'
}
}
}
}
function loopThroughObjRecurs (obj, propExec) {
for (var k in obj) {
if (typeof obj[k] === 'object' && obj[k] !== null) {
loopThroughObjRecurs(obj[k], propExec)
} else if (obj.hasOwnProperty(k)) {
propExec(k, obj[k])
}
}
}
// then apply to each property the task you want, in this case just console
loopThroughObjRecurs(foo, function(k, prop) {
console.log(k + ': ' + prop)
})
Si desea recuperar un árbol de relaciones, puede utilizar Object.keys de forma recursiva.
function paths(item) {
function iter(r, p) {
var keys = Object.keys(r);
if (keys.length) {
return keys.forEach(x => iter(r[x], p.concat(x)));
}
result.push(p);
}
var result = [];
iter(item, []);
return result;
}
var data = {
foo: {
bar: '',
child: {
grand: {
greatgrand: {}
}
}
}
};
console.log(paths(data));
Esto se puede ampliar para buscar valores dentro de una estructura de objeto que coincidan con una función:
function objectSearch(rootItem, matcher) {
const visited = [];
const paths = [];
function iterate(item, path) {
if (visited.includes(item)) {
return;
}
visited.push(item);
if (typeof item === "object" && item !== null) {
var keys = Object.keys(item);
if (keys.length) {
return keys.forEach(key => iterate(item[key], path.concat(key)));
}
}
if (matcher(item)) {
paths.push(path);
}
}
iterate(rootItem, []);
return paths;
}
function searchForNaNs(rootItem) {
return objectSearch(rootItem, (v) => Object.is(NaN, v));
}
var banana = {
foo: {
bar: "",
child: {
grand: {
greatgrand: {},
nanan: "NaN",
nan: NaN,
},
},
},
};
console.log("There's a NaN at", searchForNaNs(banana)[0].join("."), "in this object:", banana);
Considere usar escaneo de objetos . Es poderoso para el procesamiento de datos una vez que lo entiendes.
Una gran ventaja es que los elementos se recorren en orden de "eliminación segura". Entonces, si elimina uno, no arruinará el ciclo. Y tienes acceso a muchas otras propiedades como padres, etc.
// const objectScan = require('object-scan');
const obj = { foo: { bar: '', child: { grand: { greatgrand: { /* and so on */ } } } } };
objectScan(['**'], {
filterFn: ({ property }) => {
console.log(property);
}
})(obj);
// => greatgrand
// => grand
// => child
// => bar
// => foo
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>
Descargo de responsabilidad : soy el autor de escaneo de objetos