Object.unfreeze, or similar API
Michał Wadas
michalwadas at gmail.com
Mon Feb 19 20:08:39 UTC 2018
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 <joe at trusktr.io> 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
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180219/521d9206/attachment-0001.html>
More information about the es-discuss
mailing list