That's actually very useful, thanks! I have plenty of cases where I wished I could pass an object without cloning it to ensure it isn't mutated from outside. And instead of creating the Proxy right when I will emit an event (for example), I could just store the proxy somewhere so it is long-lived and to avoid GC.
*/#!/*JoePea On Mon, Feb 19, 2018 at 12:08 PM, Michał Wadas <[email protected]> wrote: > You can just do: > > const proxy = new Proxy(obj, { > set() { throw new Error(); }, > defineProperty() { throw new Error();}, > deleteProperty() { throw new Error(); } > }) > this.emit('some:event', proxy) > > > Though, it seems like an exotic use case. > > On Mon, Feb 19, 2018 at 8:56 PM, /#!/JoePea <[email protected]> wrote: > >> >> I think the ability to unfreeze an object can be useful. >> >> For example, suppose we have a library that emits events: >> >> ```js >> this.emit('some:event', this.obj) >> ``` >> >> Maybe we want to try to prevent external listeners from modifying the >> event payload without having to clone `this.obj`, otherwise cloning can >> cause "jank" from GC during animations that should be smooth. >> >> So, what if there was a way to unfreeze an object in the scope in which >> the object was frozen? >> >> ```js >> Object.freeze(obj) // instead of cloning >> this.emit('some:event', this.obj) // recommend all listeners to be >> synchronous, and not modify the payload later >> Object.unfreeze(this.obj) // in the same scope >> ``` >> >> or maybe it return an unfreeze function: >> >> ```js >> const unfreeze = Object.freeze(obj) // instead of cloning >> this.emit('some:event', this.obj) // recommend all listeners to be >> synchronous, and not modify the payload later >> unfreeze(this.obj) // only code that is given the unfreeze function can >> call it, similar to resolve/reject functions with Promises >> ``` >> >> or maybe it is more similar to setTimeout and setInterval: >> >> ```js >> const frozenKey = Object.freeze(obj) // instead of cloning >> this.emit('some:event', this.obj) // recommend all listeners to be >> synchronous, and not modify the payload later >> Object.unfreeze(frozenKey) // only code that is given the key can >> unfreeze the object associated with the key >> ``` >> >> It seems like there can be opportunity for this to be optimized, so that >> it can be faster than cloning. For example, this uses more memory and >> causes GC: >> >> ```js >> this.emit('some:event', { ...this.obj }) // creates a new object >> ``` >> >> Could the performance benefit make it worth it to have a way to unfreeze >> objects? >> >> Another use case is unlocking things only when used in certain places, as >> a "guard". In the following example, the only way to set the X rotation >> value is with the setter, which enforces that certain logic will fire, >> rather than someone from the outside modifying the readable state not using >> the setter: >> >> ```js >> >> import Privates from 'somewhere' >> >> // a private cache, using WeakMap internally >> const _ = new Privates >> >> class ThingThatRotates { >> constructor() { >> this.rotation = { x: 0, y: 0, z: 0 } >> _(this).frozen = Object.freeze(this.rotation) >> // ... >> } >> >> get rotateX() { return this.rotation.x } >> set rotateX(val) { >> this.doSomethingImportantWithTheValue(val) >> >> // unlock here, so that the value can only be set with this >> setter. >> Object.unfreeze(_(this).frozen) >> this.rotation.x = val >> _(this).frozen = Object.freeze(this.rotation) >> >> this.emitAnEventWithTheValue(val) >> this.etc(val) >> } >> >> // ... >> } >> >> ``` >> >> I know, I can probably just keep `rotation` in the private cache, but >> then it isn't readable. Maybe I want that to be readable as a convenient >> shortcut. F.e. >> >> ```js >> // outside code >> const r = new ThingThatRotates >> >> // X rotation might be animated by some other tool >> >> const {x, y, z} = r.rotation // for convenience, no cloning involved. >> >> ``` >> >> This is a completely contrived example I just made up right now. I can >> probably think of more. It seems like it could be good for performance in >> cases where we don't want modification from the outside... >> >> >> /#!/JoePea >> >> _______________________________________________ >> es-discuss mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/es-discuss >> >> >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

