2012-08-24 13 views
7

windowのすべての宣言された変数の中で、'StackOverflow'のような値を検索したいとします。 私はこのコードでそれを行うことができます。グローバル変数とそのプロパティの値を再帰的に検索

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

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

私の問題は、私はこのような結果を達成するために、あまりにも深く行くとwindowのオブジェクト(および独自のネストされたオブジェクト)を通して検索したいということです。

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

私は継承の問題を抱えていますオブジェクトのメソッドこれを行う方法はありますか?

+0

継承されたメソッドの問題はどういう意味ですか? –

答えて

11

ディープ検索が、再帰関数なしでは

機能再帰が内部スタックの制限や廃棄物のメモリを持って呼び出します。

さらなる特徴は、検索配列の形で

再帰オブジェクト保護を加え、オブジェクトは参照としてのみ格納されるため、あまりにも多くのメモリを消費しません。

オブジェクト自体が値と一致する場合は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; 
} 

問題

を関数にintial変数名を通過することなく、我々は最初から完全修飾変数名を返すことができません。私は解決策について考えることはできませんし、もしあれば私は驚くでしょう。

変数名は、オブジェクトのキーとして有効で、他の無効な変数名と同様に、角かっこを使用して値を指定する必要があります。私が考えることができるいくつかのソリューションがあります。正規表現では、各変数名が有効であることを確認し、そうでない場合は、角括弧表記を使用します。この問題の重大な問題は、reg-exが長いページであることです。代わりに、角括弧しか使用できませんでしたが、これはOPの元の質問に実際には当てはまりません。

'searched'という配列のindexOf呼び出しは、非常に大きなオブジェクトでは少し重いかもしれませんが、私はまだ別の方法について考えることはできません。

改善

関数はマッチの配列を返した場合以外のコードを少しクリーンアップから、それもいいだろう。これはまた、返された配列に再帰オブジェクトへの参照が含まれないという点で、別の問題を引き起こします。関数が結果フォーマット構成パラメーターを受け入れる可能性があります。

+0

これをFirebugコンソールのほぼすべてのページで実行すると、「操作は安全ではありません」と表示されます。私はいくつかのエラーキャッチスキームを使いこなしていますが、私はここに追加するのに十分なものを見つけることはできません。たぶん、誰かがこれを回避する改善を行うことができますか? – eternalnewb

4

これは動作するはずです。結果を得るために再帰を使用します。

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

大部分のブラウザは、あまりにも多くのループについて警告を発するでしょう。

+2

あなたの関数が 'window'をあなたの' obj'として使っていることに注目してください。 – Ravan

+0

@Ravan:私の答えをチェックしてください。 – JCOC611

関連する問題