>  object.keys only returns own properties -- it doesn't return the properties 
> of the prototype.

You're right, for some reason I have it firmly planted in my head that 
Object.keys is suppose to produce the same set of property names that for-in 
produces but that certainly isn't what the spec.

allen
From: Oliver Hunt [mailto:[email protected]]
Sent: Friday, May 07, 2010 12:42 PM
To: Allen Wirfs-Brock
Cc: Mark S. Miller; [email protected]; es-discuss; Mike Stay; 
[email protected]
Subject: Re: Yet more ambiguities in property enumeration


On May 7, 2010, at 12:15 PM, Allen Wirfs-Brock wrote:


I don't think it is valid to use Object.keys as part of your definition of 
for-in  because that leaves you with a circular definition as the specification 
for Object.keys says it orders the keys in the same order used  by for-in.

I wasn't meaning to use this as a spec worthy definition, but as a way to see 
how for in was evaluated across object and it's prototypes.


Ignoring algorithms for the moment and simply looking at semantics, I don't see 
how your interpretation makes any sense at all.  The semantics of prototype 
inheritance creates the illusion that inherited properties are part of the 
inheriting object unless they are explicitly over-ridden by an own property. 
The semantics you describe break this illusion by essentially allowing the 
[[enumerable]] attribute of an inherited property to over-ride the 
[[enumerable]] attribute of a same-named own property.  This is essentially the 
same mistake that the JScript has historically made with ES1-3 when it allowed 
an inherited dontenum attribute to suppress the enumeration of a like-name own 
property.   I think there is universal agreement that JScript was wrong in this 
regard.  What you are proposing is equally wrong  but with the boolean value of 
the attribute reversed.

This isn't a proposal, this is what we do, and we do it this way because in the 
past our failure to do so broke sites.


I believe that the correct list of enumerated names for for-in  (in the absence 
of side-effects that  modify properties or property attributes) is:
 ...<snip>...
This is also the list of names that Object.keys should produce. The actual 
order of the names in the result of the above function is not specified by ES5. 
 The prose of 12.6.4 (but not the algorithm) concerning deleted properties 
means that side-effects that delete properties should be handled as if for-in 
was then implemented as:

getEnumerableNames(obj).forEach(function(n) {if (n in obj) 
execute-for-in-body-with-n});

object.keys only returns own properties -- it doesn't return the properties of 
the prototype.


But note that since the order is undefined,  if the body does any deletes there 
is no guarantee whether  you will or won't see a key that is subject to 
deletion.  The only guarantee is that if all occurrences of a particular 
property name (there may be multiple along the prototype chain) are deleted  
before processing that name, then the for-in body will not be execute for that 
name.
Things are even more unspecified if properties are added as side-effects or if 
enumerable attribute values are dynamically changed.

It seems a bug in the spec that this isn't defined -- the order of enumeration 
of own properties in actual implementations is the order of addition, it has to 
be this or sites will break.  JSC originally followed the ES3 spec (which 
didn't defined ordering) and sites broke.  This is the set of constraints the I 
know are necessary:
1. Order of enumeration of own properties is the order of addition
2. You can't enter the loop with a property that has been added since the start 
of iteration
3. You can't enter the loop with a property has been removed since that start 
of iteration
4. You can't enter the loop with the same value multiple times

Sites break if you don't enforce any one of these constraints.  We know this 
because the behaviour of iteration in JSC has been specifically implemented to 
enforce these constraints as a result of re-world site breakage.

It should be easy to see how each of these constraints is enforced in the 
example code i listed earlier.

The place where there has historically been a difference between 
implementations is precisely what happens with properties from the prototype 
chain.

--Oliver
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to