Skip to content
Advertisement

Recursive JavaScript function is losing the return value

I want to search a string in a nested JSON object. If the string found in an object, I need to return that object.

I am using a recursive function to achieve this. The problem is, the function is recursing until the end and not returning the object found.

Please see the entire code in jsfiddle

function search(obj, name) {
    console.log(obj["name"], ",", name, obj["name"] == name);

    if (obj["name"] == name) {
        return obj; //NOT RETURNING HERE
    } 
    if (obj.children || obj._children) {
        var ch = obj.children || obj._children;
        //console.log(ch);
        ch.forEach(function(val) {
            search(val, name)
        });
    }
    return -1;
}

search(myJson, "VM10-Proc4")

I am not sure what is going wrong.

Answer

The correct return value is getting lost in the chain of recursive function calls. After the correct value is found, any additional searches made will return incorrect values from that point on.

A couple ways to handle this:

1. Cancel the search

When the correct value is found, immediately return it all the way up the recursive stack, without searching any more of the current arrays or the nested arrays. In other words, cancel the rest of the search.

@Barmer’s answer is an example of this. The key part of his code is the use of for loops rather than the each method to iterate through the arrays, since it’s much easier to interrupt a for loop.

2. Store the value somewhere safe

When the correct value is found, store it somewhere safe, allow the rest of the search to continue, and after the initial function call has finished access the value. The simplest way is to store the correct value in a global variable, though that’s not a good practice as it violates the encapsulation of the function.

@shyam’s answer presents a cleaner solution: Passing a reference to a global variable as a function parameter, setting the parameter when the correct value is found, and then accessing the global variable after the initial function call has finished.

Choosing between the two

In laymen’s terms, the intended logic of the function could be summed up as follows: When you find what you’re looking for, stop, and let me know what it is immediately. The only reason to continue searching would be if multiple pieces of data needed to be found. I’m assuming that’s not the case here.

Of the two approaches, #2 is a quick-fix workaround that should work fine but will further confuse anyone who’s trying to understand the intended logic of the function. Why is the search continuing if it’s only looking for a single piece of data that’s already been found?

#1 is a refactoring of the function so that it behaves more consistently with the intended logic, which would make the function easier to understand. The function stops searching when it finds what it needs.

Advertisement