如何阻止 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);
}
}
我在 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);
}
}