在JavaScript中更改映射中的值和闭包中的引用



从技术上讲,这是TypeScript,但问题在于JS。

我有一个名为Animal的接口,如下所示:

interface Animal {
name: string;
speak(): void;
}
function animal(name: string): Animal {
return {
name,
speak() {
console.log('This animal does not know how to speak!');
},
};
}

我有另一个接口Dog,它扩展了Animal,并附带了一个函数,该函数扩展了一个常规对象并使其成为Dog

interface Dog extends Animal {
breed: string;
}
function dog<T extends Animal>(animal: T, breed: string): T & Dog {
const obj = {
breed,
...animal,
speak() {
console.log(`${obj.name} says Woof!`);
},
};
return obj;
}

我还有另一个名为Competition的界面,代表所有参加比赛的动物。这不仅限于狗。

interface Competition extends Animal {
prize: number;
}
function competition<T extends Animal>(animal: T, prize: number): T & Competition {
return {
prize,
...animal,
};
}

到这里为止一切都很好。但现在,我需要一个Map,它存储一只动物以及它的主人的名字(假设一个人只能拥有一只动物)。

const map: Map<string, Animal> = new Map();

现在有一个叫约翰的家伙,他有一只西伯利亚哈士奇叫福。

map.set('John', dog(animal('Foo'), 'Siberian Husky'));

约翰让福参加比赛,福获得第二名。

map.set('John', competition(map.get('John'), 2));

然而,在比赛中,约翰看到另一只狗也叫福,于是决定给他的狗改名。

map.get('John').name = 'Timmy';
map.get('John').speak(); // Foo says Woof!

问题是speak访问了在我调用dog(...)时处于闭包中的对象的name,在本例中为"Foo"。更改对象中变量的值不会修改闭包中的值。

我的问题是,我该如何更改闭包中的值?我似乎想不出一种方法不需要对我目前的系统进行重大更改。

游乐场

使用方法上下文this.name而不是obj.name(注意Typescript中的this,由于JavaScript的工作方式,键入可能不准确)。

最新更新