There are several errors in your code:
- You
util.findVal recursively, but do not return the result of the call. The code should be return util.findVal(...) - You are not passing the attribute name
key recursive call - You are not processing the link loop feature
- If the object contains a key, as well as a subobject containing a key, the return value is random (depends on the sequence in which the keys are analyzed)
The third problem is what can cause infinite recursion, for example:
var obj1 = {}, obj2 = {}; obj1.x = obj2; obj2.y = obj1;
if you just keep looking for a recursive search in obj1 or obj2 , this can lead to infinite recursion.
Unfortunately, for reasons unclear to me in Javascript, it is not possible to recognize an “identity” object ... (which is what Python id(x) does), you can only compare the object with another. This means that in order to find out if an object was already visible in the past, you need to perform a linear scan with known objects.
ES6 adds the ability to verify the identity of an object using Set and Map , where objects can be used as keys. This allows faster (sublinear) search time.
For example, a search solution that runs in order of depth:
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; }
taking into account the object and the attribute name, it returns all the values found with this name at the first depth of their detection (there can be several values: for example, when searching for {x:{z:1}, y:{z:2}} key "z" two values are at the same depth).
The function also correctly processes structures that refer to themselves, avoiding an endless search.