> 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

