从技术上讲,这是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的工作方式,键入可能不准确)。