打字稿装饰器不是唯一的问题

Typescript decorators not unique issues

我有以下情况,我想使用装饰器来基本上更改函数的获取,目标是获取 return 如果已设置或未设置特定变量。

我有执行此操作所需的代码,但我认为我不完全了解装饰器的工作原理。我在打字稿操场上创建了以下示例:here

function PropertyDecorator(
    target: Object, // The prototype of the class
    propertyKey: string | symbol // The name of the property
) {
    let value = false;

    console.log('hit');

    return {
    get: () => {
        return value;
    },
    set: (val: string) => {
        value = val.toLowerCase() !== 'false';
    },
    enumerable: true,
    configurable: true
    };
}

class PropertyDecoratorExample {

    @PropertyDecorator
    name: string;

    @PropertyDecorator
    name2: string;

    constructor() {
        console.log('New instance');
        console.log(this.name, 'should be false');
        this.name = 'hey';
        console.log(this.name, 'should be true');
        console.log(this.name2, 'should be false');
    }
}

new PropertyDecoratorExample();
new PropertyDecoratorExample();

有没有从例子中看出,对象的第一个实例是正确的(查看控制台) 但是,第二个实例由于某种原因与第一个实例保持相同的上下文,有什么想法吗?或者这里有什么问题?

问题是您的装饰器在每个 class 每个装饰字段只调用一次。因此,装饰器内的箭头函数将捕获 value 变量并将其用于装饰器 class 的所有实例。

你不应该将实例数据保存在装饰器函数变量中(因为如上所述它们将被共享)你可以将数据保存在当前实例上,如果你使用常规函数,则可以在内部访问 get/set 函数使用 this

function PropertyDecorator(
    target: Object, // The prototype of the class
    propertyKey: string // The name of the property
): any {
    console.log('hit');

    return {
      get: function ()  {
        return !!this[propertyKey + 'value'];
      },
      set: function(val: string) {
        this[propertyKey + 'value'] = val.toLowerCase() !== 'false';
      },
      enumerable: true,
      configurable: true
    };
}

class PropertyDecoratorExample {

    @PropertyDecorator
    name: string;

    @PropertyDecorator
    name2: string;

    constructor() {
        console.log('New instance');
        console.log(this.name, 'should be false');
        this.name = 'hey';
        console.log(this.name, 'should be true');
        console.log(this.name2, 'should be false');
    }
}

new PropertyDecoratorExample();
new PropertyDecoratorExample();