Я хочу поиграть с декораторами.
В качестве первой цели я пытаюсь создать простой декоратор для свойства, в котором я хочу иметь простые геттеры и сеттеры.
Здесь мой текущий код:
function fooddecorator(target, key, descriptor) {
const {
configurable,
enumerable,
value,
initializer,
} = descriptor
const initialValue = initializer ? initializer.call(this) : value
return {
configurable,
enumerable,
set(newValue) {
console.log("SETTER CALLED: ", newValue)
Object.defineProperty(this, key, {
configurable,
enumerable,
writable: true,
value: newValue,
})
return newValue
},
get() {
console.log("GETTER CALLED")
return initialValue
},
}
}
class SimpleClass {
@fooddecorator
food = "Pizza"
}
const sc = new SimpleClass()
console.log("sc.food 1: ", sc.food)
sc.food = "Burgers"
console.log("sc.food 2: ", sc.food)
sc.food = "Steak"
console.log("sc.food 3: ", sc.food)
const sc2 = new SimpleClass()
console.log("sc2.food 1: ", sc2.food)
sc2.food = "Pasta"
console.log("sc2.food 2: ", sc2.food)
sc2.food = "Cola"
console.log("sc2.food 3: ", sc2.food)
console.log("sc.food 4: ", sc.food)
Вывод:
GETTER CALLED
sc.food 1: Pizza
SETTER CALLED: Burgers
sc.food 2: Burgers
sc.food 3: Steak
GETTER CALLED
sc2.food 1: Pizza
SETTER CALLED: Pasta
sc2.food 2: Pasta
sc2.food 3: Cola
sc.food 4: Steak
Проблемы:
1.) Как только set()
вызывается в первый раз, он явно перезаписывает свойство this.key
со своим собственным дескриптором свойства. Это приводит к перезаписи get()
и set()
.
Проблема заключается в том, что я не нашел другого решения для назначения нового значения (= newValue
) свойству. Например, это дает сбой с "превышен размер стека ..." - ошибка рекурсии:
set(newValue) {
this[key] = newValue
}
2.) get()
в настоящее время возвращает только initialValue
. Я не нашел способ вернуть начальное значение при первом доступе, а затем вернуть впоследствии установленные значения. Это параллельная проблема с моей предыдущей проблемой, потому что я также получаю ошибку рекурсии, если я делаю это:
get() {
return this[key]
}
Я уверен, что понимаю что-то очень фундаментальное, но простое неправильно. Я просто понятия не имею, что это может быть.
То, что я тоже пробовал:
Я также пытался создать «скрытую» переменную, которой я присваиваю значения:
function fooddecorator(target, key, descriptor) {
...
let internalValue = initialValue
return {
configurable,
enumerable,
set(newValue) {
internalValue = newValue
},
get() {
return internalValue
}
}
}
Сначала я думал, что это сработало. Но в основном это свойство food
stati c, потому что internalValue
используется во всех случаях SimpleClass
. Если присмотреться к этому, становится очевидным, почему это так. Однако я понятия не имею, что с этим делать.
JSFiddle здесь: https://jsfiddle.net/e5sfmbv3/1/