如何让作为属性的类实例修改所属父类实例的属性?
嘿,针对你提出的两个面向对象问题,结合你给的代码示例,我来给你一步步拆解解决方案:
问题1:如何让一个类能够影响实例化它的类?
核心思路是让被实例化的类(比如你的Gpa类)持有父类实例(Person实例)的引用,或者通过回调函数的方式让父类把修改自身的逻辑传递给子类。这样子类就能直接操作父实例的属性或触发父实例的方法,从而实现“影响”。
问题2:属性实例如何修改父实例的属性?(结合你的示例)
我们直接基于你给出的代码修改,实现Gpa实例修改所属Person实例的happynessHistory属性的需求,分两种常用方案:
方案1:让子类持有父实例的直接引用
这是最直观的方式,在创建Gpa实例时把当前Person实例传递进去,保存在Gpa内部,之后就能直接访问父实例的属性了:
class Person { constructor(name, gpa) { this.name = name; this.happynessHistory = []; // 创建Gpa时传入当前Person实例 this.gpa = new Gpa(gpa, this); } } class Gpa { constructor(startingGpa, person) { this.score = startingGpa; // 保存父实例的引用 this.person = person; } updateGpa(newGpa) { const oldScore = this.score; this.score = newGpa; // 直接修改Person实例的happynessHistory属性 if (newGpa > oldScore) { this.person.happynessHistory.push(`因为GPA从${oldScore}涨到${newGpa},${this.person.name}很开心!`); } else if (newGpa < oldScore) { this.person.happynessHistory.push(`因为GPA从${oldScore}降到${newGpa},${this.person.name}有点难过...`); } else { this.person.happynessHistory.push(`${this.person.name}的GPA没变化,心情平和~`); } } } // 测试效果 const alice = new Person('Alice', 3.5); alice.gpa.updateGpa(3.8); console.log(alice.happynessHistory); // 输出: ["因为GPA从3.5涨到3.8,Alice很开心!"] alice.gpa.updateGpa(3.6); console.log(alice.happynessHistory); // 输出: ["因为GPA从3.5涨到3.8,Alice很开心!", "因为GPA从3.8降到3.6,Alice有点难过..."]
方案2:使用回调函数降低耦合度
如果你不想让Gpa直接依赖Person的结构,可以让Person传递一个回调函数给Gpa,Gpa只需要调用这个函数就能间接修改父实例的属性,这样两个类的耦合度更低:
class Person { constructor(name, gpa) { this.name = name; this.happynessHistory = []; // 传递一个添加记录的回调函数给Gpa this.gpa = new Gpa(gpa, (message) => { this.happynessHistory.push(`${this.name}:${message}`); }); } } class Gpa { constructor(startingGpa, addHappynessRecord) { this.score = startingGpa; // 保存回调函数 this.addHappynessRecord = addHappynessRecord; } updateGpa(newGpa) { const oldScore = this.score; this.score = newGpa; let message; if (newGpa > oldScore) { message = `GPA从${oldScore}涨到${newGpa},超开心!`; } else if (newGpa < oldScore) { message = `GPA从${oldScore}降到${newGpa},有点emo...`; } else { message = "GPA没变化,心态平稳~"; } // 调用回调函数,间接修改Person的属性 this.addHappynessRecord(message); } } // 测试效果 const bob = new Person('Bob', 3.2); bob.gpa.updateGpa(3.2); console.log(bob.happynessHistory); // 输出: ["Bob:GPA没变化,心态平稳~"] bob.gpa.updateGpa(3.5); console.log(bob.happynessHistory); // 输出: ["Bob:GPA没变化,心态平稳~", "Bob:GPA从3.2涨到3.5,超开心!"]
注意点
- 方案1要留意循环引用问题:如果
Person和Gpa互相持有引用,在某些场景下可能影响JavaScript的垃圾回收,但一般业务场景下无需过度担心。 - 方案2更符合单一职责原则,
Gpa只需要专注于GPA的逻辑,不需要了解Person的内部结构,扩展性更好。
内容的提问来源于stack exchange,提问作者billbitt
相关产品推荐
相关产品推荐

