2012-02-24 16 views
1

すべてのブラウザで再帰的ツリーwindowをダンプする関数を作成しようとしています。私が直面するとすぐに分かった問題は、無限の物体(window.window.window.window)と関係がありました。ただ笑いのために、私はとにかくそれを試して、私は期待どおりエラーがあった。 Uncaught RangeError: Maximum call stack size exceeded(Chromeのテスト)Javascriptウィンドウのツリー再帰と無限オブジェクト

だから、これは単純だっ起こすつもりだったオブジェクトに対してチェックするための最初のアプローチ:

if (variable != 'window' && variable != 'top' && variable != 'self' && variable != 'frames') 

私はカップルを働いた、と私は単に逃してしまうことかもしれないと思っています。それは良い理論でしたが、私はまだ最大のスタックエラーを取得します。そこで、私はwindowとChromeのコンソールを入力し、手動で[DOMWindow]のすべてのタイプを検索してこのリストに追加しました。ことをやっている間、私は私の次のアプローチに私をもたらしたInfinity: Infinity値を、気づい:

if (typeof namespace[variable]['Infinity'] === 'undefined') 

私はまだそれに最大スタックエラーを得たので、私はそう、Googleの検索のビットをした、約isFiniteを学びました今私が持っている:(編集:実際に私はちょうどisFiniteが、私はそれが思ったものではありません実現)

if (isFinite(tree[variable])) 

エラーがようやく去っていきましたが、この方法の問題点は、window内のすべてのオブジェクトは、のためにfalseを返すされていることですこのため、再帰は失敗します。私は、いくつかのアプローチはおそらくブラウザ間で互換性がないと考えていますが、平均的な時間に少なくとも1つのブラウザで動作させることができればいいと思います。

無限ループの原因となるオブジェクトを確認するにはどうすればよいですか?

ここだけ興味があるかもしれない人のために、私のコードです:

(function() { 
    window.onload = function() { 
     window.onload = ''; // don't want to get our own code 
     console.log((function (namespace) { 
      tree = {}; 
      for (var variable in namespace) { 
       /* gonna need these later 
       var variable_typeof = typeof namespace[variable], 
        variable_object_tostring = Object.prototype.toString(namespace[variable]); 
       */ 

       //if (variable != 'window' && variable != 'top' && variable != 'self' && variable != 'frames') 
       //if (typeof namespace[variable]['Infinity'] === 'undefined') 
       if (isFinite(tree[variable])) 
        tree[variable] = arguments.callee(namespace[variable]); 
       else tree[variable] = 'Infinity'; 
      } 
      return tree; 
     })(window)); // Start from root 
    } 
})(); 

更新:
ここでは、私は最終的に興味がある人のために、思い付いたの作業製品です。
GGGは、彼の助力のために言及する価値があります。あなたの問題で無限再帰を防ぐために

function loop (namespace) { 
    if (namespace['__infinite_test']) return '[[recursion]]'; // It's infinite 
    namespace['__infinite_test'] = true; // Note that we've been through this object 
    var tree = {}; 
    for (var variable in namespace) { 
     try { // For an issue in Chrome throwing an error 
      namespace[variable]['__tester'] = null; 
      delete namespace[variable]['__tester']; 
     } 
     catch (e) { 
      tree[variable] = namespace[variable]; 
      continue; 
     } 
     if (namespace.propertyIsEnumerable(variable)) tree[variable] = loop(namespace[variable]); 
     else tree[variable] = namespace[variable]; 
    } 
    return tree; 
} 
console.log(loop(window)); 

答えて

1

一つの方法は、すでに訪問したすべてのオブジェクトのリストを追跡することで、あなたはすでに訪問したオブジェクトが発生した場合、あなたはそれに再帰しません。

リストに含まれていないオブジェクトが発生した場合は、そのオブジェクトをリストに追加してから再帰的に処理します。

+0

私も実際にそれを試みましたが、不完全なリストになりました。私はこれに頼るかもしれないし、それを具体化するための何らかの方法を見つける。たぶん、私は別のレベルを実行する別の関数を作成し、欠落している要素を追加することができます。これについてブレーンストームする必要があります。 – Shea

+0

@andrewjackson - あなたの実装に欠陥があったと思われます。試したコードを共有し、コメントを付けることができます。 – jfriend00

+0

私はそれを廃却しました、私はそれを書き直す必要があります。それは私のいわゆる「最初のアプローチ」の前でさえ、実際に私が試した最初のものでした。私は今すぐ書き直し、それを更新して、自分の持っていることを知らせます。 – Shea