对象之间的循环引用是一种不好的实践吗?

26

我有一个模型,它将使用“Model.validator”来携带验证器实例,并且我需要验证器能够访问模型的属性。因此,我想出了以下解决方案:

var Validator = function(model) {
    this.model = model;
};

var Model = function() {
    this._attributes = {};
    this.validator = new Validator(this);
};

var model = new Model();

这段代码在这两个对象之间创建了一个循环引用。这是一种会导致内存泄漏的不良实践吗?你有其他实现方法吗?

附言:我在 Angular.js 作用域中看到过这样的对象之间的循环引用。


7
在 IE6 可能会有这种情况,但现代的 JS 引擎完全能够处理垃圾回收循环。 - georg
3
即使在IE6中,如果它们只是纯JS对象而不包含DOM,也是如此。 - Bergi
1
请注意,循环引用在序列化时(例如通过JSON.stringify())会导致问题。 - Uriel
3个回答

23

这种代码在当今的浏览器中不会导致内存泄漏;如MDN所述,所有主流浏览器现在都有标记和清理垃圾回收机制(可以处理循环引用),例如自版本3起Firefox就拥有了循环收集器。

从架构的角度来看,这种代码在两个对象之间引入了适度的紧密耦合(如果其中一个发生轻微变化,则需要检查另一个是否也需要更改),因此应尽可能避免使用。但本质上并没有什么问题。


7
"适度紧密耦合" - 你很擅长轻描淡写。 - Erick Robertson
1
@ErickRobertson:嗯,在其他语言中也有基于类的继承,友元,“只是该死的完成工作”反射...至少在这里,您只能混淆公共接口。 :-) - Jon

4

对于垃圾回收来说,这不是一个问题:任何新的垃圾回收器(>IE6)都可以很好地处理循环引用!

但如果您正在执行递归函数或打印对象,则可能会出现问题。

因此,答案是:除非您自己搞砸了,否则这不是问题 :-)。


3

我相信不会有任何问题。大多数浏览器的JS解析器可以在垃圾回收时处理循环依赖关系。这里不再存在潜在的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接