Типографские декораторы не уникальные проблемы - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть следующий случай, я хочу использовать декоратор для базового изменения функции get, цель в том, чтобы функция get возвращала, была установлена ​​конкретная переменная или нет.

У меня есть код, необходимый для этого, но я не совсем понимаю, как работают декораторы. Я создал следующий пример на машинописной площадке: здесь

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();

имеет, как вы можете видеть из примера, первый экземпляр объекта правильный (проверьте консоль) хотя второй экземпляр почему-то сохраняет тот же контекст, что и первый, есть идеи, почему? или что тут не так?

1 Ответ

0 голосов
/ 15 ноября 2018

Проблема в том, что ваш декоратор вызывается ровно один раз на класс для каждого декорированного поля. Таким образом, функции стрелок внутри декоратора перехватывают эту переменную value и будут использовать ее для всех экземпляров декорированного класса.

Вы не должны хранить данные экземпляра в переменных функции декоратора (потому что, как объяснено выше, они будут совместно использоваться). Вы можете сохранить данные в текущем экземпляре, который, если вы используете обычную функцию, доступен внутри функций 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();
...