1

如果我在 2 个对象之间有 2 向关系,例如AB相关,BA相关,我怎样才能保持这种一致性,以使 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;

从逻辑上讲,如果哈利的妻子是温蒂,那么温蒂的丈夫就是哈利。

我需要一种保持这种关系一致的方法。因此,我创建了一个 setter 方法,Husband并通过以下划线前缀表示该wife变量应被视为私有变量。

function Husband() {
    this._wife;
    this.setWife = function(wife) {
        this._wife = wife;
        wife.husband = this;
    }
}

现在描述这种关系很简单,并鼓励一致性:

harry.setWife(wendy);

同样,最好有相反的选项:

wendy.setHusband(harry);

为此,我setHusband在 上创建一个方法Wife,并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也保持一致。

4

3 回答 3

2

一种简单的方法是只检查冗余值并提前中止:

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 等),或者具有不需要设置器的直接属性,并注意保持数据更新。

于 2017-03-31T03:54:01.787 回答
1

这样的事情是做你所要求的一种方法:

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();
于 2017-03-31T03:30:22.363 回答
1

._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);
  }
}
于 2017-03-31T04:01:57.817 回答