Enumerability

Claude Pache claude.pache at gmail.com
Fri Jan 10 12:58:50 PST 2014


Le 9 janv. 2014 à 12:21, Axel Rauschmayer <axel at rauschma.de> a écrit :

> I’m still really unhappy about enumerability in ECMAScript. I find it frustratingly inconsistent:
> 
> * At the moment, only Object.keys and the for-in loop are affected by it.
> * In ECMAScript 6, Object.assign will also ignore non-enumerable properties.

You forgot an important fact: While legacy `for/in` loop takes inherited properties into account, all newer constructs are only affected by *own* enumerable properties. You also forgot to mention `JSON.stringify`, which also takes only own enumerable properties into account. I guess that, in the long run, enumerability will be really significant for own properties only.

> * Built-in prototype methods are non-enumerable, as is property `length` of arrays.
> * In ECMAScript 6, prototype methods created by classes are enumerable, the prototype method `constructor` is non-enumerable (as it is by default in all functions).
> 
> I’ve seen various explanations for what enumerability is:
> 
> 1. Something that won’t matter in the long run. But then why are we introducing new constructs that take it into consideration?
> 2. Something that one has to do properly so that old code doesn’t break. Here, it’d be helpful to be concrete: where can this happen? The obvious case is for-in for instances of built-in constructors.
> 3. Signaling an intent of sharing. But what does that mean in practice? Why are built-in methods different from user-defined methods in this regard?
> 4. A way of marking a method as private. Again: why the divergence between built-in methods and user-defined methods?
> 
> I think it would really help the design of ECMAScript going forward if we had a definitive and complete explanation of what enumerability is now and what it should be in the future. I’m trying to make sense of it and to explain it to others and continue to fail.
> 

I can't provide a definite abstract explanation, but here is a practical situation where I've found non-enumerability a useful feature, although it does not exactly fit any of the four explanations you cited. Consider some tree structure:

    obj = { foo: 1, bar: 2, children : [ { foo: 5, bar: 4 }, { foo: 2, bar: 4, children: [...] } ] }

When walking through such a tree, I typically want to have access (for example) to the parent of a node (just like the `parentNode` method of `Node` objects in the DOM). For that end, I define a *non-enumerable* `_parent` property on each node, which refers back to its parent node. Now, although I have polluted each node with a supplementary property, 

* I can happily invoke `Object.keys` on a node, and it will give me back the correct answer;
* I can happily serialise my tree using `JSON.stringify`, and it won't complain that it can't handle cyclic structures. After deserialising it with `JSON.parse`, I just have to recursively reconstruct the `_parent` back-references;
* etc.

—Claude



More information about the es-discuss mailing list