2009-09-29 41 views
32

我想知道如果有人有一個很好的,在JavaScript的循環引用的工作示例?我知道這對於閉包來說非常容易,但是我很難把這個包裹在腦子裏。我可以在Firebug中剖析一個例子,我將非常感激。Javascript中循環引用的示例?

感謝

+0

感謝您的答案;我可以看到Josh的例子發生在一個產品應用程序中,我可能會遇到許多綁定事件。我很想防止這種泄漏發生在運行IE6的客戶端上。糾正我,如果我錯了,但這只是瀏覽器IE6及以下的問題?大多數現代瀏覽器都實現了一個垃圾收集器,能夠找到這些類型的引用? – MatthewJ 2009-09-29 18:20:04

回答

41

一種簡單的方式來創建一個循環引用是爲具有指本身在一個屬性的對象:

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

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

這裏foo對象包含對自身的引用。

隨着封閉件,這通常是更隱含的,通過僅具有在範圍的循環引用,而不是像一些對象的顯式屬性:

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功能指circular可變的,並且從而本身。它隱含地提到自己,創建一個循環引用。即使circular現在超出範圍,它仍然從函數範圍引用。簡單的垃圾收集器將不會識別該循環,並且不會收集該函數。

+0

感謝您的解釋。這是一個很容易理解的簡單例子。 – MatthewJ 2009-09-29 18:40:01

+0

「簡單的垃圾收集器不會識別這個循環並且不會收集函數」的好處是什麼?在你的例子中,這是否意味着「循環」總是可以訪問並且可以更新?我問,因爲我的API有一個循環對象,它攜帶數據庫事務上下文,所以看起來它會隨着新的上下文信息一直更新,所以避免垃圾收集看起來是一個很好的計劃。我關門了嗎? – agm1984 2017-06-24 18:57:14

+0

只是爲了獲得一些額外的完整信息,我注意到如果我嘗試使用'console.log(JSON.stringify(circular))'快照它,它會拋出循環引用錯誤。我很好奇爲什麼我不能以這種方式查看當前的情況。 – agm1984 2017-06-24 18:59:27

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

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

    function mouse() { 
    } 
    } 
}

正如你所看到的,處理程序嵌套在附加器,這意味着它是在調用者的範圍之內關閉。

+0

感謝喬希,看起來像是一個現實的例子,可能會在實際應用中發生什麼 – MatthewJ 2009-09-29 18:40:32

+1

@Josh Stodola你能解釋爲什麼這是一個問題嗎?我試圖剖析這段代碼,並理解爲什麼會導致內存泄漏。謝謝。 – Amir 2016-05-28 13:30:33

+0

@Amir爲了附加mouse()函數DOM對象必須引用整個連接函數,並且attachEvent在這個連接函數中,這使得循環引用更多詳細信息在這裏 https://support.microsoft.com/zh-cn/kb/kb/830555 – Zgr3doo 2016-10-27 12:50:56

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

印刷ab將返回Circular

+7

這是一個循環引用,但是「印刷」是什麼意思?你的答案意味着JS引擎實際上會返回字符串「Circular」... – nnnnnn 2012-10-21 07:17:44

+0

他的意思是如果你'console.log(a)'然後它打印'[[[Circular]]]'。 – 2016-01-15 21:51:04

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()