14

'StackOverflow'で宣言されているすべての変数で、 のような値を検索したいとしましょうwindow。私はこのコードでそれを行うことができます:

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

このコードは、この値を持つ変数の名前を返します (または何も返しません)。したがって、 value で変数を宣言した場合'StackOverflow'、それは正常に検出されます。

私の問題は、次windowのような結果を得るために、さらに深く 's オブジェクト (およびそれ自体のネストされたオブジェクト) も検索したいということです。

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

オブジェクトの継承されたメソッドに問題があります。これを行う方法はありますか?

4

4 に答える 4

26

再帰関数呼び出しなしのディープ検索

関数再帰には内部スタック制限があり、メモリを浪費します。

追加された追加機能

検索配列の形式での再帰的オブジェクト保護。もちろん、オブジェクトは参照としてのみ保存されるため、メモリをあまり消費しません。

オブジェクト自体が値と一致する場合は true を返します。それ以外の場合は、false に一致する '' を返します。

配列は山かっこ表記を使用します。

コード

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;
}

問題

初期変数名を関数に渡さないと、最初から完全修飾変数名を返すことはできません。解決策が思い浮かびません。解決策があったとしたら驚きです。

スペースを含む変数名は、他の無効な変数名と同様に、オブジェクトのキーとして有効です。これは、山かっこを使用して値を指定する必要があることを意味します。私が考えることができるいくつかの解決策があります。正規表現は、各変数名をチェックして有効であることを確認し、有効でない場合は山かっこ表記を使用します。これに関する最も重要な問題は、正規表現がページ長であることです。別の方法として、山かっこのみを使用することもできますが、これは OP の元の質問には当てはまりません。

「検索された」配列のindexOf呼び出しは、非常に大きなオブジェクトでは少し重いかもしれませんが、私はまだ代替案を思いつきません.

改良点

コードを少し整理するだけでなく、関数が一致の配列を返すとよいでしょう。これにより、返された配列に再帰オブジェクトへの参照が含まれないという別の問題も発生します。おそらく、関数は結果フォーマット構成パラメーターを受け入れることができます。

于 2012-08-24T04:25:29.783 に答える
5

これはうまくいくはずです。再帰を使用して結果を達成します。

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;
}
于 2012-08-24T02:26:58.917 に答える
0

ソリューションを再帰的にします。オブジェクトがある場合は、関数を再度呼び出します。

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');

ほとんどのブラウザーでは、ループが多すぎると警告が表示されるに違いありません。

于 2012-08-24T02:28:11.593 に答える