【问题标题】:Circular reference instantiation循环引用实例化
【发布时间】:2016-08-21 14:53:57
【问题描述】:

我想实例化两个相互依赖的类,如下所示:

this.a = null;
this.b = null; 
this.a = new A({
  b: this.b
}
this.b = new B({
  a: this.a
}

问题是如果我这样做,b 如果我将它交给构造函数,则为 null。如何以“优雅”的方式解决这个鸡或蛋的问题?还是必须在通过方法实例化后设置对b的引用?

【问题讨论】:

  • AB的构造函数中做。例如。对于A,如果通过null,则设置this.b = new B(this);。当B 被传递一个a != null 时,递归结束。 AB 交换的方式相同。
  • 我认为唯一的方法是在两个对象都实例化后使用setter来完成循环。

标签: javascript oop circular-reference


【解决方案1】:

我建议将问题移至AB 的构造函数。

在这种情况下,您可以利用条件(间接)递归:

function A(b)
{
    this.b = b || new B(this);
}
function B(a)
{
    this.a = a || new A(this);
}

通过使用||,您可以确保对A(this)B(this) 的调用不会分别创建另一个B/A,从而结束“鸡/蛋”问题。

然后你可以像这样使用它们

this.a = new A();
this.b = this.a.b;

this.b = new B();
this.a = this.b.a;

如果存在AB 合法地将其.b.a 设置为null 的情况,您可以使用undefinednull 来区分这些情况,并更改构造函数相应地:

function A(b)
{
    this.b = b === undefined ? new B(this) : b;
}
function B(a)
{
    this.a = a === undefined ? new A(this) : a;
}

如果AB 的构造函数需要其他参数,或者由于其他原因不应该自己构造另一个BA,您可以将this 实例从创建范围传递给它们(因为它包含 ab 字段,其值仅在访问时确定,而不是在构造 AB 时确定):

function A(container)
{
    this.container = container;
    // Access B via this.container.b
}
function B(container)
{
    this.container = container;
    // Access A via this.container.a
}
this.a = new A(this);
this.b = new B(this);

如果AB 并不意味着拥有对容器对象的完全访问权限,您可以创建中间对象来代替它使用,例如:

var aProxy = { a: null };
var bProxy = { b: null };
this.a = aProxy.a = new A(bProxy);
this.b = bProxy.b = new B(aProxy);

如果由于某种原因这也是不可接受的,那么您唯一的选择是稍后通过手动分配或通过 setter 函数更改 a.bb.a 的值。

【讨论】:

  • 但请注意,这种方法将两个类本身紧密耦合在一起,而不是让它们的容器完成工作并传递实例。
  • 这就是它对我不起作用的原因。我想我必须通过 setter 进行分配,即使它有点脏。
  • @landunder 需要明确的是,前两种方法将类联系在一起,后两种(其中 A 和 B 被传递一个容器)没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-04
相关资源
最近更新 更多