递归搜索全局变量及其属性中的值

时间:2022-03-09 23:35:29

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

假设我想在窗口中的所有声明变量中搜索值,如'*'。我可以用这段代码做到:

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

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

此代码将返回具有此值的变量的名称(或不返回任何内容)。所以,如果我声明了一个值为'*'的变量,它将成功找到它。

My problem is that I want to go deeper and search thru window's objects (and its own nested objects) too, to achieve a result like this:

我的问题是我想更深入地搜索窗口的对象(以及它自己的嵌套对象),以实现这样的结果:

var x = '*'                     // returns 'x'
var y = { a : '*' }             // returns 'y.a'
var z = { a : { b: '*' } }      // returns 'z.a.b'

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

我对Object的继承方法有问题。有没有办法做到这一点?

3 个解决方案

#1


12  

Deep search but without the recursive function calls

深度搜索但没有递归函数调用

Functional recursion has internal stack limits and wastes memory.

函数递归具有内部堆栈限制并浪费内存。

Additional features added

添加了其他功能

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

以搜索数组的形式提供递归对象保护;当然,它不会消耗太多内存,因为对象仅存储为引用。

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

如果对象本身与值匹配,则返回true。否则它将返回''匹配为false的''。

Arrays use angle-bracket 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 name into the function, we can't return the fully qualified variable name from the beginning. I can't think of a solution and I woud be surprised if there was one.

如果不将初始变量名称传递给函数,我们就无法从头开始返回完全限定的变量名称。我想不出解决方案,如果有的话,我会感到惊讶。

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

带空格的变量名作为对象的键是有效的,其他无效变量名也是如此,它只是意味着必须使用尖括号来处理该值。我能想到几种解决方案。正则表达式检查每个变量名称以确保它是有效的,如果不是,则使用尖括号表示法。最重要的问题是reg-ex是一个页面长。或者,我们只能使用尖括号,但这不是真正的OP原始问题。

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

对''搜索'数组的indexOf调用对于非常大的对象可能有点沉重但我还不能想到另一种选择。

Improvements

改进

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

除了清理代码之外,如果函数返回一个匹配数组也会很好。这也引发了另一个问题,即返回的数组不包含对递归对象的引用。也许该函数可以接受结果格式配置参数。

#2


5  

This should work. It uses recursion to achieve 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;
}

#3


0  

Make your solution 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, '*');

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

我敢打赌,大多数浏览器会因太多循环而发出警告。

#1


12  

Deep search but without the recursive function calls

深度搜索但没有递归函数调用

Functional recursion has internal stack limits and wastes memory.

函数递归具有内部堆栈限制并浪费内存。

Additional features added

添加了其他功能

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

以搜索数组的形式提供递归对象保护;当然,它不会消耗太多内存,因为对象仅存储为引用。

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

如果对象本身与值匹配,则返回true。否则它将返回''匹配为false的''。

Arrays use angle-bracket 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 name into the function, we can't return the fully qualified variable name from the beginning. I can't think of a solution and I woud be surprised if there was one.

如果不将初始变量名称传递给函数,我们就无法从头开始返回完全限定的变量名称。我想不出解决方案,如果有的话,我会感到惊讶。

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

带空格的变量名作为对象的键是有效的,其他无效变量名也是如此,它只是意味着必须使用尖括号来处理该值。我能想到几种解决方案。正则表达式检查每个变量名称以确保它是有效的,如果不是,则使用尖括号表示法。最重要的问题是reg-ex是一个页面长。或者,我们只能使用尖括号,但这不是真正的OP原始问题。

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

对''搜索'数组的indexOf调用对于非常大的对象可能有点沉重但我还不能想到另一种选择。

Improvements

改进

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

除了清理代码之外,如果函数返回一个匹配数组也会很好。这也引发了另一个问题,即返回的数组不包含对递归对象的引用。也许该函数可以接受结果格式配置参数。

#2


5  

This should work. It uses recursion to achieve 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;
}

#3


0  

Make your solution 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, '*');

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

我敢打赌,大多数浏览器会因太多循环而发出警告。