2009-09-29 24 views
32

誰かが循環参照の良い、実用的な例をjavascriptで持っているのだろうかと思いましたか?私はこれがクロージャーとは信じられないほど簡単だと知っていますが、これの周りに私の脳を包み込むのに苦労しました。私がFirebugで解読できる例が最も高く評価されます。あなたが見ることができるようにJavascriptの循環参照の例?

おかげ

+0

回答ありがとうございます。ジョシュの例がプロダクションアプリで起こっていることがわかります。そこでは、たくさんのバウンドイベントがあります。私はIE6を実行しているクライアントでこのリークが起きないようにしたいと考えています。私が間違っている場合は私を修正しますが、これはIE6以下のブラウザでのみ問題になりますか?現代のブラウザーのほとんどは、これらのタイプの参照を見つけることができるガベージコレクターを実装していますか? – MatthewJ

答えて

41

簡単な方法は、プロパティにそれ自体を参照するオブジェクトを有することである:ここ

function Foo() { 
    this.abc = "Hello"; 
    this.circular = this; 
} 

var foo = new Foo(); 
alert(foo.circular.circular.circular.circular.circular.abc); 

fooオブジェクト自体への参照を含みます。クロージャと

これは単に範囲内の循環参照を有することによってではなく、いくつかのオブジェクトの明示的な性質として、通常より暗黙的である:circularで保存機能がcircular変数を意味ここ

var circular; 

circular = function(arg) { 
    if (arg) { 
    alert(arg); 
    } 
    else { 
    // refers to the |circular| variable, and by that to itself. 
    circular("No argument"); 
    } 
} 

circular("hello"); 
circular(); 

、及びそれによってそれ自体に。暗黙的に参照を保持し、循環参照を作成します。 circularがスコープから外れても、関数スコープから参照されます。単純なガベージコレクタはこのループを認識せず、関数を収集しません。

+0

説明sthありがとう。それは理解しやすい非常に簡単な例です。 – MatthewJ

+0

"単純なガベージコレクタはこのループを認識せず、関数を収集しません"というメリットは何ですか?ここの例では、 '循環型'は常にアクセス可能で更新可能であることを意味しますか?私のAPIはデータベーストランザクションコンテキストを運ぶ循環オブジェクトを持っているので、新しいコンテキスト情報で常に更新されるように思えるので、ガベージコレクションを避けるのは良い計画のようです。私は閉じますか? – agm1984

+0

さらに、いくつかの完全な情報については、 'console.log(JSON.stringify(circular)) 'でスナップショットを作成しようとすると循環参照エラーが発生することに気付きました。私はなぜこのように現在の文脈を見ることができないのか不思議です。 – agm1984

11
window.onload = function() { 
    hookup(document.getElementById('menu')); 

    function hookup(elem) { 
    elem.attachEvent("onmouseover", mouse); 

    function mouse() { 
    } 
    } 
}

は、ハンドラは、それが呼び出し元の範囲にわたり閉鎖されていることを意味する、アタッチ内にネストされています。循環参照を作成する

+0

ありがとうジョシュは、実際のアプリケーションで起こる可能性のある現実的な例のようです – MatthewJ

+1

@Josh Stodolaなぜこれが問題であるか説明できますか?私はこのコードを解読し、なぜメモリリークを引き起こすのか理解しようとしています。ありがとう。 – Amir

+0

@Amir mouse()関数をアタッチするためにはDOMオブジェクトは全体の関数を参照する必要があり、attachEventはこの関数の内部にあり、循環参照をここで詳しく説明します https://support.microsoft.com/en-gb/kb/830555 – Zgr3doo

1
var b = []; 
var a = []; 
a[0] = b; 
b[0] = a; 

印刷aまたはbCircularを返します。

+7

これは循環参照ですが、「印刷」とはどういう意味ですか?あなたの答えは、JSエンジンが実際に文字列 "Circular"を返すことを意味します... – nnnnnn

+0

彼は 'console.log(a)'なら '[[Circular]]]'を出力します。 –

13

さらに単純ではあるが、配列自体を「含む」。

var arr = []; 
arr[0] = arr; 
1
function circular(arg){ 
    var count = 0; 

    function next(arg){ 
     count++; 
     if(count > 10) return; 
     if(arg){ 
      console.log('hava arg: ' + arg); 
      next(); 
     }else{ 
      console.log('no arg'); 
      next('add'); 
     } 
    } 
    next(); 
} 
circular(); 

円形とクロージャと:例を参照してください。

7

おそらく環状オブジェクトを定義する最短方法です。

a = {}; a.a = a; 
2

またはES6を使用して:

あなたが行うことができます
class Circular { 
    constructor() { 
    this.value = "Hello World"; 
    this.self = this; 
    } 
} 

circular = new Circular(); 
1

  • window.window...window
  • var circle = {}; circle.circle = circle;
  • var circle = []; circle[0] = circle; or circle.push(circle)
  • function Circle(){this.self = this}; var circle = new Circle()