如何阻止 JavaScript 通过引用传递 class?

How can I stop JavaScript from passing a class by reference?

我在 class 的构造函数中有以下代码(为了问题的目的而缩短):

constructor(effect: EffectInstance, names: string[], count?: number) {
    this.effect = effect; // instance of a class "Effect"
    let name; for (name of names) {
        this.custom.set(name, this.effect); // custom: Map
    }
}

EffectInstance is the type of this class, which is generic

当我在 class 的方法中更改 this.effect.name 时,或者当我从 Map this.custom 中获取效果并更改其名称时,两者都会更改。

据我所知,这是由于 JavaScript 对对象的传递引用行为,因为我 100% 确定我没有修改我不修改的值想要修改。 (我希望能够重命名 custom 映射中的 Effect 实例,但保持 this.effect.name 不变)

我试图用 constructor() 中的参数重新实例化 classes,但这引发了一个新问题:我会丢失类型,而且我似乎无法理解了解如何解决这个问题。这是我尝试过的:

(EffectInstance,供参考:<EffectInstance extends Effect>)

constructor(effect: EffectInstance, names: string[], count?: number) {
    this.effect = effect;
    let altEffect = effect instanceof PlayerEffect ? new PlayerEffect(effect.name, effect.ignoreRaces) : new Effect(effect.name);
    let name; for (name of names) {
        this.custom.set(name, altEffect);
    }
}

这样做,TS 在 altEffect 上引发此错误:

TS2345: Argument of type 'Effect' is not assignable to parameter of type 'EffectInstance'.   'Effect' is assignable to the constraint of type 'EffectInstance', but 'EffectInstance' could be instantiated with a different subtype of constraint 'Effect'.

我需要停止传递引用行为或保留 EffectInstance 包含的类型。我该怎么做?

大多数语言通过引用传递对象,因此这不是 javascript 的独特行为。

如果您想传递 class 实例的副本而不是原始实例,并将克隆发送到您不想发送原始实例的地方。

class Car {
  constructor(name) {
    this.name = name;
  }
}

let orignalClass = new Car('BMW');

let cloneClass = Object.assign(Object.create(Object.getPrototypeOf(orignalClass)), orignalClass)

console.log(orignalClass);
console.log(cloneClass);

// now both can be updated individually
orignalClass.name = 'BMw-1';
cloneClass.name = "BMW-copy"

console.log("after update");
console.log(orignalClass);
console.log(cloneClass);

通过您的代码,this.custom类型应该是 Effect。

constructor(effect: EffectInstance, names: string[], count?: number) {
    this.custom = new Map<string, Effect>(); // altEffect type could be PlayerEffect or Effect
    this.effect = effect;
    let altEffect = effect instanceof PlayerEffect ? new PlayerEffect(effect.name, effect.ignoreRaces) : new Effect(effect.name);
    let name; for (name of names) {
        this.custom.set(name, altEffect);
    }
}