2016-08-21 116 views
1

我想要實例兩類這兩者是互相依賴的,像這樣:循環引用實例

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

的問題是,如果我這樣做b爲空,如果我把它交給構造函數。我怎樣才能以「優雅」的方式解決這個雞或雞蛋問題?或者,我必須通過方法在實例化之後將參考設置爲b

+0

在'A'和'B'的構造函數中做。例如。對於'A',如果它通過'null',則設置'this.b = new B(this);'。當'B'傳遞'a!= null'時,遞歸結束。交換'A'和'B'的方法相同。 – Siguza

+2

我認爲唯一的方法是在實例化兩個對象後使用setter來完成循環。 – Claudiu

回答

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); 

如果這也是出於某種原因不能接受,那麼你唯一的選擇是後來改的a.bb.a值通過手動分配或通過setter功能。

+2

但請注意,這種方法將兩個類本身緊密結合在一起,而不是讓它們的容器完成工作並傳遞實例。 – Bergi

+0

這是它不適合我的原因。我認爲我必須由制定者來完成任務,即使它有點髒。 – landunder

+0

@landunder明確地說,前兩種方法將類組合在一起,後兩種方法(其中A和B通過一個容器)不這樣做。 – Siguza