2009-09-29 80 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()