Recursively search for a value in global variables and its properties

Let's say that I want to search for a value, such as 'StackOverflow' , in all declared variables in a window . I can do this with this code:

 function globalSearch(obj, value) { for(var p in obj) if(obj[p] == value) return(p); } globalSearch(window, 'StackOverflow'); 

This code will return the name of the variable that has this value (or returns nothing). So, if I declared a variable with the value 'StackOverflow' , it will successfully find it.

My problem is that I want to go deeper and look for window objects (and my own nested objects) to achieve this result:

 var x = 'StackOverflow' // returns 'x' var y = { a : 'StackOverflow' } // returns 'ya' var z = { a : { b: 'StackOverflow' } } // returns 'zab' 

I'm having problems with inherited methods of objects. Is there any way to do this?

+9
source share
4 answers

Deep search, but without calls to recursive functions

Functional recursion has internal stack limitations and waste memory.

Additional features added

Recursive protection of objects in the form of the desired array; Of course, it does not use too much memory, since objects are stored only as links.

Returns true if the object itself matches the value. Otherwise, it will return '', which will be false.

Arrays use the notation of angle brackets.

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 name to the function, we cannot return the full variable name from the very beginning. I cannot come up with a solution, and I would be surprised if it were.

Variable names with spaces are valid as a key to the object, like other invalid variable names, it just means that the value must be addressed using angle brackets. There are several solutions that I can think of. Regex checks each variable name to make sure it is valid and uses the angle brackets if it is not. The main problem is that reg-ex is a page for a long time. As an alternative, we could only use angle brackets, but this is not entirely true for the original OP question.

Calling indexOf for a found array can be a bit heavy on very large objects, but I still cannot come up with an alternative.

<strong> Improvements

Besides clearing the code a bit, it would be nice if the function returned an array of matches. This also causes another problem: the returned array will not contain references to recursive objects. Perhaps the function may accept a result format configuration parameter.

+15
source

That should work. To achieve the result, recursion is used.

 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; } 
+5
source

Make your decision recursive. If you have 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 am sure that most browsers will be warned in too many cycles.

0
source

This code, based on another answer, allows you to find all possible matches of values.

 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); } 
0
source

All Articles