Freezing object properties or array values, whilst keeping them extensible

David Bruant bruant.d at gmail.com
Tue Jun 4 09:41:21 PDT 2013


Le 04/06/2013 06:57, Andy Earnshaw a écrit :
> Something that occurred to me today is that we have methods for 
> locking down objects in different ways except for preventing changes 
> to existing properties.  We have:
>
>  - Object.seal to prevent new properties being added or existing 
> properties being deleted
>  - Object.preventExtensions to prevent new properties being added
>  - Object.freeze to prevent new properties being added or existing 
> properties being altered/deleted
>
> Let's say, though, that my library has a function that accepts an 
> object as an argument, performs some changes to the values of 
> properties on that object and returns it to the developer's code for 
> use in a different function provided by my library.  If I didn't want 
> the developer changing any of the properties the function sets, I'd 
> have to copy all properties across to a new object.
If you didn't create the object yourself, you're subject to the 
decisions of the provider when it comes to guaranteeing something about 
an object. You can try to add your own stuff, but it's up to the 
provider to decide whether they let you do that.
I would recommend using a WeakMap for this type of use case (attaching 
information to an object you didn't create).

> That's all well and good, but what if it's an array?  The length 
> property of an array isn't configurable, so you can't prevent it being 
> written without freezing it which, in turn, prevents extensions 
> altogether.
Object.defineProperty(a, 'length', {writable: false}) should work. 
Firefox had a long-standing bug making it non-compliant on this... which 
has been fixed recently [1] and will be part of Firefox 23.

> Array.create might have taken care of that, depending on how it was 
> implemented, but it seems as though that's been deferred in favour of 
> the <| operator proposal.
I'm not sure I understand what you're saying here. Do you want to return 
the same or a different object? For sure, your caller will know if you 
returned a different object (because it can compare the argument and the 
return value)

> If it's not too late for ES6 proposals, I'd like to suggest that we 
> add either an function to freeze only existing properties of an 
> object, e.g. Object.lock(), or a function to freeze arrays, e.g. 
> Array.freeze().  The latter would only freeze the length property and 
> existing array index properties, keeping it extensible.
Your use case suggests the need for a well-encapsulated weakmap, no need 
for new constructs, I think. We have enough low-level control over 
object I feel.

David

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=858381#c67


More information about the es-discuss mailing list