[ACCEPTED]-Recursively search for a value in global variables and its properties-global-variables

Accepted answer
Score: 27

Deep search but without the recursive function calls

Functional recursion has internal stack 33 limits and wastes memory.

Additional features added

Recursive object 32 protection in the form of a searched array; It 31 doesn't use up too much memory of course 30 as the objects are only stored as references.

Return 29 true if the the object itself matches the 28 value. Otherwise it would return '' which 27 would match to false.

Arrays use angle-bracket 26 notation.

The code

function globalSearch(startObject, value) {
    var stack = [[startObject,'']];
    var searched = [];
    var found = false;

    var isArray = function(test) {
        return Object.prototype.toString.call( test ) === '[object Array]';
    }

    while(stack.length) {
        var fromStack = stack.pop();
        var obj = fromStack[0];
        var address = fromStack[1];

        if( typeof obj == typeof value && obj == value) {
            var found = address;
            break;
        }else if(typeof obj == "object" && searched.indexOf(obj) == -1){
           if ( isArray(obj) ) {
              var prefix = '[';
              var postfix = ']';
           }else {
              var prefix = '.';
              var postfix = '';
           }
           for( i in obj ) {
              stack.push( [ obj[i], address + prefix + i + postfix ] );
           }
           searched.push(obj);
        }
    }
    return found == '' ? true : found;
}

Problems

Without passing the intial variable 25 name into the function, we can't return 24 the fully qualified variable name from the 23 beginning. I can't think of a solution and 22 I woud be surprised if there was one.

Variable 21 names with spaces are valid as the key to 20 an object, as are other invalid variable 19 names, it just means that the value must 18 be addressed using angle-brackets. There 17 are a couple of solutions I can think of. Regex 16 check each variable name to make sure it's 15 valid and use angle-brackets notation if 14 it is not. The overriding problem with this 13 is that the reg-ex is a page long. Alternatively, we 12 could only use angle-brackets but this isn't 11 really true to the OPs original question.

The 10 indexOf call on the array 'searched' might 9 be a bit heavy on very large objects but 8 I can't yet think of an alternative.

Improvements

Apart 7 from cleaning up the code a little, it would 6 also be nice if the function returned an 5 array of matches. This also raises another 4 issue in that the returned array would not 3 contain references to recursive objects. Maybe 2 the function could accept a result format 1 configuration parameter.

Score: 5

This should work. It uses recursion to achieve 1 the result.

function globalSearch(obj, value) {
    for(var p in obj)
        if(obj[p] == value){
            return(p);
        }else if(typeof obj[p] == "object" && obj[p] != obj){
           var te = globalSearch(obj[p], value);
           if(te!=false){ return p + "." + te }
        }
    return false;
}
Score: 0

Make your solution recursive. If you have 3 an object, call your function again.

function globalSearch(obj, value) {
    for(var p in obj) {
        if (obj[p] == value) {
            return(p);
        } else if (typeof obj[p] === "object") {
            var recursiveCheck= globalSearch(obj[p], value);
            if (recursiveCheck) {
                return p + "." + recursiveCheck;
            }
        }
    }
}
globalSearch(window, 'StackOverflow');

I bet 2 most browsers will hit a warning for too 1 much looping.

Score: 0

This code, based on the other answer, allows 1 for all possible value matches to be found.

function globalSearch(startObject, value, returnFirstResult = false) {
    var stack = [[startObject,'']];
    var searched = [];
    var found = new Set();

    var isArray = function(test) {
        return Object.prototype.toString.call( test ) === '[object Array]';
    }

    while(stack.length) {
        var fromStack = stack.pop();
        var obj = fromStack[0];
        var address = fromStack[1];

        if( typeof obj == typeof value && obj == value) {
            if (returnFirstResult) {
                return address == '' ? false : address;
            }
            found.add(address)
        }if(typeof obj == "object" && searched.indexOf(obj) == -1){
           if ( isArray(obj) ) {
                var prefix = '[';
                var postfix = ']';
           }else {
                var prefix = '.';
                var postfix = '';
           }
           for( i in obj ) {
                stack.push( [ obj[i], address + prefix + i + postfix ] );
           }
           searched.push(obj);
        }
    }
    return Array.from(found);
}

More Related questions