After the few questions made above, it looks like the function should:
- Assume the input is always an object.
- Assume it might encounter arrays in its way.
- Assume it must stop after meeting one value (in case multiple value exists).
The provided input code given by the OP does not handle array cases.
Below code is sampled to work with these sample cases:
- Plain nested object structure.
- Object with nested arrays of objects or elements.
Below function accepts a second argument which is a callback to evaluate whether the element met is actually the one we're looking for. In this way, it's easier to handle more complex checks.
The recursive approach is kept and, once the key is met, the function simply return
to avoid unnecessary searchs.
const foo = { data: { data2: { data3: 'worked' }, data21: 'rand' }, data01: 'rand01' };
const fooWithArrays = {
data: {
data2: {
data3: 'not here'
},
data4: [
{ data5: 'worked' },
{ data6: 'not me' }
]
}
};
const fooWithExpression = {
data: {
data2: {
data3: { id: 15, name: 'find me!' }
},
data21: {
data25: 'not me'
}
}
};
const findKeyByValue = (obj, equalsExpression) => {
// Loop key->value pairs of the input object.
for (var [key, v] of Object.entries(obj)) {
// if the value is an array..
if (Array.isArray(v)) {
// Loop the array.
for (let i = 0; i < v.length; i++) {
// check whether the recursive call returns a result for the nested element.
let res = findKeyByValue(v[i], equalsExpression);
// if so, the key was returned. Simply return.
if (res !== null && res !== undefined) return res;
}
}
// otherwise..
else {
// if the value is not null and not undefined.
if (v !== null && v !== undefined) {
// if the value is an object (typeof(null) would give object, hence the above if).
if (typeof(v) === 'object') {
// check whether the value searched is an object and the match is met.
if (equalsExpression(v)) return key;
// if not, recursively keep searching in the object.
let res = findKeyByValue(v, equalsExpression);
// if the key is found, return it.
if (res !== null && res !== undefined) return res;
}
else {
// finally, value must be a primitive or something similar. Compare.
let res = equalsExpression(v);
// if the condition is met, return the key.
if (res) return key;
// else.. continue.
}
}
else continue;
}
}
}
console.log( findKeyByValue(foo, (found) => found === 'worked') );
console.log( findKeyByValue(fooWithArrays, (found) => found === 'worked') );
console.log( findKeyByValue(fooWithExpression, (found) => found && found.id && found.id === 15) );