Как сделать так чтобы значение свойство после вызова defineProperty не изменялось на undefined?
У меня есть код
const obj = {
props: "Hello"
}
function useChange(obj, props, fn) {
Object.defineProperty(obj, props, {
set(newValue) {
fn(newValue)
}
})
}
useChange(obj, "props", (newValue) => {
console.log(newValue)
})
obj.props = "Привет"
console.log(obj.props) //undefined
У меня проблема, что после вызова defineProperty значение obj.props равно не "привет", а undefined.
При это если я делаю данный вариант, то выходит ошибка:
const obj = {
props: "Hello"
}
function useChange(obj, props, fn) {
Object.defineProperty(obj, props, {
set(newValue) {
fn(newValue)
obj[props] = newValue;
}
})
}
useChange(obj, "props", (newValue) => {
console.log(newValue)
})
obj.props = "Привет"
console.log(obj.props) //undefined
Uncaught RangeError: Maximum call stack size exceeded
Если знаете как сделать так чтобы после вызова defineProperty свойство не изменяло своё значение на undefined, пишите. Заранее спасибо за ответ!
Ответы (1 шт):
Вызывая Object.defineProperty(obj, props
свойство props
полностью переписывается на новое. В данном случае новое свойство содержит только сеттер. Сеттер, который никуда не сохраняет новое значение. Поэтому и получить его невозможно.
В зависимости от того, как планируется применять функцию useChange
варианты решения могут быть разными.
Самый просто способ - просто сохранять куда-то значение, либо в тот же объект в качестве свойства с другим именем,
либо воспользоваться замыканием.
Например:
const obj = {
props: "Hello"
}
function useChange(obj, props, fn) {
var propsVal = obj[props]; // используем замыкание
Object.defineProperty(obj, props, {
set(newValue) {
fn(newValue)
propsVal = newValue;
},
get() {
return propsVal;
}
})
}
useChange(obj, "props", (newValue) => {
console.log(newValue)
})
obj.props = "Привет"
console.log(obj.props) //undefined
const obj2 = {
props: "Hello"
}
function useChange2(obj, props, fn) {
var key = Symbol(props);
obj[key] = obj[props]; // используем специальное имя
Object.defineProperty(obj, props, {
set(newValue) {
fn(newValue)
obj[key] = newValue;
},
get() {
return obj[key];
}
})
}
useChange2(obj2, "props", (newValue) => {
console.log(newValue)
})
obj2.props = "Привет2"
console.log(obj2.props) //undefined