Saltar al contenido

Buscar de forma recursiva el valor en el objeto por nombre de propiedad

Solución:

Podrías usar Object.keys e iterar con Array#some.

function findVal(object, key) {
    var value;
    Object.keys(object).some(function(k) {
        if (k === key) {
            value = object[k];
            return true;
        }
        if (object[k] && typeof object[k] === 'object') {
            value = findVal(object[k], key);
            return value !== undefined;
        }
    });
    return value;
}

var object =  { photo: { progress: 20 }};
console.log(findVal(object, 'progress'));

Tu código tiene algunos errores:

  • Estás llamando recursivamente util.findVal pero sin devolver el resultado de la llamada. El código debe ser return util.findVal(...)
  • No pasa el nombre del atributo key a la llamada recursiva
  • No está manejando la posibilidad de un bucle de referencia
  • Si un objeto contiene una clave y también un subobjeto que contiene la clave, el valor que se devuelve es aleatorio (depende de la secuencia en la que se analizan las claves)

El tercer problema es qué puede causar una recursividad infinita, por ejemplo:

var obj1 = {}, obj2 = {};
obj1.x = obj2; obj2.y = obj1;

si sigues buscando de forma recursiva en obj1 o obj2 podría conducir a una recursividad infinita.

Lamentablemente por razones que no me quedan claras en Javascript es imposible conocer el objeto “identidad” … (lo que Python id(x) hace) solo se puede comparar un objeto con otro. Esto significa que para saber si un objeto ya se ha visto en el pasado, necesita un escaneo lineal con objetos conocidos.

ES6 agregó la posibilidad de verificar la identidad del objeto con Set y Map donde los objetos se pueden utilizar como claves. Esto permite tiempos de búsqueda más rápidos (sub-lineales).

Una solución de búsqueda que se ejecuta en orden de profundidad podría ser, por ejemplo:

function findVal(obj, key) {
    var seen = new Set, active = [obj];
    while (active.length) {
        var new_active = [], found = [];
        for (var i=0; i<active.length; i++) {
            Object.keys(active[i]).forEach(function(k){
                var x = active[i][k];
                if (k === key) {
                    found.push(x);
                } else if (x && typeof x === "object" &&
                           !seen.has(x)) {
                    seen.add(x);
                    new_active.push(x);
                }
            });
        }
        if (found.length) return found;
        active = new_active;
    }
    return null;
}

dado un objeto y un nombre de atributo, devuelve todos los valores encontrados con ese nombre en la primera profundidad en que se encuentran (puede haber más de un valor: por ejemplo, al buscar {x:{z:1}, y:{z:2}} por la llave "z" dos valores están a la misma profundidad).

La función también maneja correctamente las estructuras de autorreferencia evitando la búsqueda infinita.

intente cambiar la declaración else como esta

return util.findVal(object[key],propName)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *