首页 > 解决方案 > 在 JavaScript 中更改 map 中的值和闭包中的引用

问题描述

从技术上讲,这是 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();

现在有一个叫约翰的人,他有一只名叫Foo的西伯利亚哈士奇。

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

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

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

然而,在比赛中,约翰看到另一只狗也被命名为 Foo,因此决定重新命名他的狗。

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

问题是在我调用时speak访问闭包中的对象,在这种情况下,。更改对象中变量的值不会修改闭包中的值。namedog(...)"Foo"

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

操场

标签: javascripttypescriptclosures

解决方案


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


推荐阅读