用另一个类属性/方法扩充所有对象

时间:2018-05-16 13:32:05

标签: javascript ecmascript-6 es6-class

想象一下,我有两个班级

class Point {
}

class EditablePoint extends Point {
  // list of additional properties and methods
}

function edit(editablePoint) {
  //
}

let point = new Point();
edit(point);

如何使用其他类方法/属性扩充所有对象?

任何prototype黑客都不会为我工作。似乎我无法解决这个问题,而不是重新创建对象或手动分配类的其他属性或使用循环。我想要一些清洁的解决方案。

免责声明 :这看起来像一个反模式我同意但是我有大量Point个数组,并且只在我需要编辑的超级稀有场合他们和我想在没有引入任何复制的情况下就地这样做,因为阵列是巨大的。

为什么我不喜欢让所有点都具有可编辑的属性,并希望将它们放在原型上:

  • 每个对象实例变得更大,而且我想要的最少
  • 它与代码阅读器沟通不畅

3 个答案:

答案 0 :(得分:0)

您所要求的是技术上可行的

let pointProto = Point.prototype;
let editProto = EditablePoint.prototype;

for (let memberName in editProto) {
    if (typeof editProto[memberName] === 'function'
        && !(memberName in pointProto)) {
        pointProto[memberName] = editProto[memberName];
    }
}

这将实现您所描述的内容:Point类的所有实例现在都具有与EditablePoint实例相同的方法(!(memberName in pointProto)子句确保我们不会覆盖已定义的方法。

但是,正如你自己所说的那样,这是一个大规模反模式,因为此时你正在模糊两个类之间的界限,以至于不清楚为什么它们甚至作为单独存在班;看到Point被用作EditablePoint的数组,就好像是100%肯定的方式来混淆那些正在阅读你的代码的人。如果你认为你需要这样的东西,那么重新考虑你的模型结构可能会更好。

答案 1 :(得分:0)

您可以使用Object.assign添加属性,setPrototypeOf通过将EditablePoint的原型设置为Point的原型来添加方法,但由于EditablePoint继承自Point Point您仍然拥有class Point { constructor() { this.point = true; } foo() { console.log('foo') } } class EditablePoint extends Point { constructor() { super(); this.editable = true; } bar() { console.log('bar') } } function edit(editablePoint) { Object.assign(editablePoint, new EditablePoint); Object.setPrototypeOf(editablePoint, EditablePoint.prototype) } let point = new Point(); edit(point); console.log(point) point.foo(); point.bar();种方法。



commandData




答案 2 :(得分:0)

我认为你不应该创建一个继承自EditablePoint的{​​{1}}类,并拥有编辑所需的所有方法。相反,使用组合而不是继承,并创建一个类

Point

使用编辑与编辑器关联的点所需的所有方法。这样,您可以为要编辑的数组中的点实例化尽可能少的class PointEditor { constructor(point) { this.point = point; … } … } s,而无需更改有关如何创建数组中的点的任何内容。