再帰関数呼び出しなしのディープ検索
関数再帰には内部スタック制限があり、メモリを浪費します。
追加された追加機能
検索配列の形式での再帰的オブジェクト保護。もちろん、オブジェクトは参照としてのみ保存されるため、メモリをあまり消費しません。
オブジェクト自体が値と一致する場合は 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呼び出しは、非常に大きなオブジェクトでは少し重いかもしれませんが、私はまだ代替案を思いつきません.
改良点
コードを少し整理するだけでなく、関数が一致の配列を返すとよいでしょう。これにより、返された配列に再帰オブジェクトへの参照が含まれないという別の問題も発生します。おそらく、関数は結果フォーマット構成パラメーターを受け入れることができます。