I have the following code that is using Proxy for Class setter. In my example I am tracking specific variable to update some other variables. My Setter is writing a log of all changes to Console. However if I try to modify a variable from a setter itself, variable gas modified, but the Proxy isn't called. Is it by design to avoid looping? Or am I missing something?
class darthVader { constructor() { return new Proxy(this, { set(obj, prop, value) { console.log(`Setting ${prop} to ${value}`) obj[prop] = value return true } }) } set resistance(val) { this._resistance= val this.darkSide = false } get resistance() { return this._R2D2 } } let newHero = new darthVader() newHero.resistance = 11 console.log(newHero.darkSide)
The problem is that your trap just runs obj[prop] = value
, which sets a property on the target obj
not on the proxy. What you should do instead is to use the Reflect.set
method that provides the default implementation for the set trap, and expects an optional receiver
argument. This receiver is the object that setters will be evaluated against, and you should pass the receiver
argument of the set
trap (which will refer to the newHero
proxy that you assigned resistance
to).
class DarthVader { set resistance(val) { this._resistance= val this.darkSide = false } get resistance() { return this._R2D2 } } let newHero = new Proxy(new DarthVader, { set(target, prop, value, receiver) { console.log(`Setting ${prop} to ${value}`) return Reflect.set(target, prop, value, receiver) // ^^^^^^^^^^^ // obj[prop] = value } }); newHero.resistance = 11 console.log(newHero.darkSide)
The obj
inside the set
method refers to what this
is when you do return new Proxy(this
, and that object is not a proxy, but the darthVader
instance itself - the one that's in the process of being created by the darthVader
constructor. So, when you assign to a property of obj
, you're putting a property directly on the darthVader
instance, rather than on the proxy instance (which is the newHero
). So, the proxy method doesn't get called.
If you wanted to recursively invoke the proxy, you could define it (let's say, as the variable name proxy
) before returning it from the constructor, and then reference proxy
inside the set
method, but given the current logic, this results in a stack overflow because you'd be continually calling the proxy's setter:
class darthVader { constructor() { const proxy = new Proxy(this, { set(obj, prop, value) { console.log(`Setting ${prop} to ${value}`) proxy[prop] = value return true } }) return proxy; } set resistance(val) { this._resistance = val this.darkSide = false } get resistance() { return this._R2D2 } } let newHero = new darthVader() newHero.resistance = 11 console.log(newHero.darkSide)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.