如果我在 2 个对象之间有 2 向关系,使得 A 与B相关,B 与A相关,我如何保持一致,以便 2 个对象始终相互引用?
我正在努力用语言表达我非常简单的问题,所以这里有一个非常简单的例子。我从Husband
和Wife
开始:
function Husband() { this.wife; }
function Wife() { this.husband; }
var harry = new Husband();
var wendy = new Wife();
harry.wife = wendy;
wendy.husband = harry;
从逻辑上讲,如果哈利的妻子是温蒂,那么温蒂的丈夫就是哈利。
我需要一种方法来保持这种关系的一致性。因此,我在Husband
上创建了一个 setter 方法,并表示应通过以下划线为前缀将wife
变量视为私有变量。
function Husband() {
this._wife;
this.setWife = function(wife) {
this._wife = wife;
wife.husband = this;
}
}
描述这种关系现在很简单,并鼓励一致性:
harry.setWife(wendy);
同样,最好有相反的选项:
wendy.setHusband(harry);
为此,我在Wife
上创建了一个setHusband
方法,并根据需要调整Husband
。
function Husband() {
this._wife;
this.setWife = function(wife) {
this._wife = wife;
// wife.husband = this; // <-- husband is now _husband (private)...
wife.setHusband(this); // <-- switching to a public method
}
}
function Wife() {
this._husband;
this.setHusband = function(husband) {
this._husband = husband;
husband._wife = this; // <-- Oops! _wife is private!
husband.setWife(this); // <-- Oops! this results in an infinite loop!
}
}
在这一点上,我遇到了一个障碍。我的新setHusband
方法需要能够保持一致性,但wife
现在是_wife
(私有的),调用setWife
会导致无限循环,因为它们相互累错。
我可以创建另一组像reallyJustSetHusband
这样的方法,但这似乎很愚蠢。
我的难题并不是特定于JavaScript的,但是我已经在问题中提到了它,以防需要特定的方法。
实现这两个对象之间一致性的最佳方法是什么?我忽略了什么吗?
DOM 中的类似模式
在 DOM 中,如果您调用parent.appendChild(child)
,则child.parentNode === parent
.它们永远不会不一致。如果父母有一个孩子,则孩子有相同的父母。其他关系(如nextSibling
)也保持一致。
一个简单的方法是只检查冗余值并提前中止:
function Husband() {
this._wife;
this.setWife = function(wife) {
if(this._wife == wife) return; // prevents recursion
this._wife = wife;
wife.setHusband(this);
}
}
function Wife() {
this._husband;
this.setHusband = function(husband) {
if(this._husband == husband) return; // prevents recursion
this._husband = husband;
husband.setWife(this);
}
}
您还可以将外部状态管理器(Redux、SQL 等)与更新事件一起使用,或者具有不需要资源库的直接属性,并注意保持数据更新。
像这样的事情是完成您所要求的一种方法:
function Husband() {
this.marry = function(wife) {
this.wife = wife;
wife.husband = this;
}
this.say = function() {
if (this.wife) {
console.log('Hi! I'm married to a wife!');
} else {
console.log('Hi! I'm single, no wife.');
}
}
}
function Wife() {
this.marry = function(husband) {
this.husband = husband;
husband.wife = this;
}
this.say = function() {
if (this.husband) {
console.log('Hi! I'm married to a husband!');
} else {
console.log('Hi! I'm single. No husband.');
}
}
}
var h = new Husband();
var w = new Wife();
h.marry(w);
w.say();
h.say();
._wife
不一定是私人的——妻子知道自己的丈夫,应该被允许设置他的财产。你也可以轻松突破无限循环:
class Wife() {
constructor() {
this._husband=null;
}
get husband() { return this._husband }
set husband(h) {
if (this._husband) this._husband._wife = null;
this._husband = h;
if (h && h.wife != this) h.wife = this;
}
}
如果你不想要这种内幕知识,你需要使用管理关系(可以创建、查询和破坏)的中间类Marriage
。
class Marriage {
constructor(h, w) {
this.husband = h;
this.wife = w;
}
divorce() {
this.husband.marriage = null;
this.wife.marriage = null;
}
}
class Wife() {
constructor() {
this.marriage = null;
}
get husband() {
return this.marriage && this.marriage.husband;
}
set husband(h) {
if (this.marriage) this.marriage.divorce();
if (h.marriage) h.marriage.divorce();
this.marriage = h.marriage = new Marriage(h, this);
}
}