如何在 JavaScript 中保持双向对象关系的一致性?



如果我在 2 个对象之间有 2 向关系,使得 A 与B相关,B 与A相关,我如何保持一致,以便 2 个对象始终相互引用?

我正在努力用语言表达我非常简单的问题,所以这里有一个非常简单的例子。我从HusbandWife开始:

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

相关内容

  • 没有找到相关文章

最新更新