Reputation: 382
I want to instantiate two classes which both depend on each other like so:
this.a = null;
this.b = null;
this.a = new A({
b: this.b
}
this.b = new B({
a: this.a
}
The problem is if I do so b
is null if I hand it to the constructor. How can I solve this chicken or the egg problem in an "elegant" way? Or do I have to set the reference to b
after the instantiation via a method?
Upvotes: 1
Views: 127
Reputation: 23850
I suggest moving the problem to the constructors of A
and B
.
You can leverage conditional (indirect) recursion in this case:
function A(b)
{
this.b = b || new B(this);
}
function B(a)
{
this.a = a || new A(this);
}
By using ||
, you ensure that a call to A(this)
and B(this)
will not themselves create another B
/A
respectively, thus ending the "chicken/egg" problem.
Then you can use them like
this.a = new A();
this.b = this.a.b;
or
this.b = new B();
this.a = this.b.a;
If there are cases where A
or B
legitimately have their .b
or .a
set to null
, you could use undefined
and null
to distinguish those cases, and change the constructors accordingly:
function A(b)
{
this.b = b === undefined ? new B(this) : b;
}
function B(a)
{
this.a = a === undefined ? new A(this) : a;
}
If A
and B
require other arguments to their constructor, or should for some other reason not construct another B
or A
themselves, you could pass them the this
instance from the creating scope (since that holds a
and b
fields, whose value will be determined only when accessed, not when A
and B
are constructed):
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);
If A
and B
are not meant to have full access to the container object, you could create intermediary objects to be used in its place, like:
var aProxy = { a: null };
var bProxy = { b: null };
this.a = aProxy.a = new A(bProxy);
this.b = bProxy.b = new B(aProxy);
If that is also unacceptable for some reason, then your only option is to later change the value of a.b
and b.a
by means of manual assignment or via a setter function.
Upvotes: 1