【问题标题】:Example of a circular reference in Javascript?Javascript中的循环引用示例?
【发布时间】:2010-12-02 09:10:18
【问题描述】:

我想知道是否有人在 javascript 中提供了一个良好的、有效的循环引用示例?我知道使用闭包非常容易做到这一点,但是很难将我的大脑围绕在这个问题上。非常感谢我可以在 Firebug 中剖析的示例。

谢谢

【问题讨论】:

  • 感谢您的回答;我可以看到 Josh 的示例发生在我可能有许多绑定事件的生产应用程序中。我很想防止这种泄漏发生在运行 IE6 的客户端上。如果我错了,请纠正我,但这只是 IE6 及以下浏览器的问题?大多数现代浏览器都实现了能够找到这些类型引用的垃圾收集器?

标签: javascript closures


【解决方案1】:
window.onload = function() {
  连接(document.getElementById('菜单'));

  函数连接(elem){
    elem.attachEvent("鼠标悬停", 鼠标);

    功能鼠标(){
    }
  }
}

如您所见,处理程序嵌套在附加程序中,这意味着它在调用者的范围内是封闭的。

【讨论】:

  • 感谢 Josh,这似乎是实际应用中可能发生的事情的一个现实示例
  • @Josh Stodola 你能解释为什么这是个问题吗?我试图剖析这段代码并理解为什么这会导致内存泄漏。谢谢。
  • @Amir 为了附加 mouse() 函数 DOM 对象必须引用整个连接函数,并且 attachEvent 在这个连接函数中,这使得循环引用在这里support.microsoft.com/en-gb/kb/830555
【解决方案2】:

创建循环引用的一种简单方法是在属性中拥有一个引用自身的对象:

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 现在超出范围,它仍然从函数范围中引用。简单的垃圾收集器不会识别这个循环,也不会收集函数。

【讨论】:

  • 感谢您的解释。这是一个非常简单易懂的例子。
  • “简单的垃圾收集器不会识别这个循环并且不会收集函数”有什么好处?在您的示例中,这是否意味着 circular 始终可以访问并且可以更新?我问是因为我的 API 有一个带有数据库事务上下文的循环对象,所以它似乎会一直用新的上下文信息更新,所以避免垃圾收集似乎是一个好计划。我接近了吗?
  • 为了获得一些额外的完整信息,我注意到如果我尝试使用console.log(JSON.stringify(circular)) 对其进行快照,它会引发循环引用错误。我很好奇为什么我不能以这种方式查看它以查看当前上下文。
  • "简单的垃圾收集器不会识别这个循环,也不会收集函数。" - 来吧,不能处理参考圈的东西无法获得垃圾收集器的称号。
【解决方案3】:
var b = [];
var a = [];
a[0] = b;
b[0] = a;

打印ab 将返回Circular

【讨论】:

  • 那是循环引用,但你所说的“打印”是什么意思?您的回答暗示 JS 引擎实际上会返回字符串“Circular”...
  • 他的意思是如果你console.log(a),那么它会打印[ [ [Circular] ] ]
【解决方案4】:

或者更简单,一个“包含”自身的数组。见例子:

var arr = [];
arr[0] = arr;

【讨论】:

    【解决方案5】:
    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();
    

    圆形并带有闭包。

    【讨论】:

      【解决方案6】:

      可能是定义循环对象的最短方法。

      a = {}; a.a = a;
      

      【讨论】:

        【解决方案7】:

        或者使用 ES6:

        class Circular {
          constructor() {
            this.value = "Hello World";
            this.self = this;
          }
        }
        
        circular = new Circular();
        

        【讨论】:

          【解决方案8】:

          你可以这样做:

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

          【讨论】:

            猜你喜欢
            • 2012-07-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-04
            相关资源
            最近更新 更多