DontEnum ]DontEnum ]
]
This method returns true if the property does not have the DontEnum attribute and would be enumerated
in a for in loop.
This method does not consider objects in the prototype chain.
This method cannot be used reliably because Internet Explorer does not properly
check the DontEnum attribute.
There aren't many real world uses of propertyIsEnumerable on the web.
Due to a bug in the spec, it is not a very useful method.
One popular script where propertyIsEnumerable
was used is the YUI Connection Manager. The code itself is broken and should not
be used as an example of what to do. It is one of the only uses of propertyIsEnumerable
in production code.
// connection.js for(var prop in this._http_header){ if(this._http_header.propertyIsEnumerable){ o.conn.setRequestHeader(prop, this._http_header[prop]); } }
In the code above, the property _http_header is a collection. The proceeding
property access operator, ".", will attempt to resolve the property
propertyIsEnumerable. If it can, then that value will be returned, otherwise, the value undefined
will be returned.
The value undefined is returned in Safari 2 because Safari 2 does not support
propertyIsEnumerable. In IE, Safari 3, Opera, and Mozilla, the property will be found on
Object.prototype. This value, a function, is returned. This
value is then evaluated in boolean context in the if statement.
To sum it up, this will have the net effect of filtering out _http_header properties for all
browsers that don't support propertyIsEnumerable (Safari 2), and will have no effect,
other than a useless and inefficient call up the prototype chain and an extra call to
[[ToObject]] on each _http_header and [[ToBoolean]] on the native
function for each interim String object with the _http_header value for browsers that do support propertyIsEnumerable.
It was obviously not the author's intention to filter out http headers for Safari and reduce performance by
increasing overhead, but
instead a misunderstanding of the propertyIsEnumerable method (it's not a property) and a lack
of testing.
For user-defined object types, Object.prototype.propertyIsEnumerable,
as defined by ECMA-262,
offers nothing more than Object.prototype.hasOwnProperty.
This is due to a fault in
the ECMAScript specification.
(§15.2.4.7)
Object.prototype.propertyIsEnumerable (V)When thepropertyIsEnumerablemethod is called with argument V, the following steps are taken:
- Let O be this object.
- Call
ToString(V).- If O doesn't have a property with the name given by Result(2), return false.
- If the property has the
DontEnumattribute, return false.- Return true.
In JScript, step #4 is is ignored. Some user-defined objects are not enumerable. We have seen this in the
for inloop. We can show this by testingpropertyIsEnumerable.
NOTE
This method does not consider objects in the prototype chain.
It is impossible to create a new property that has the DontEnum attribute.
All user defined properties are therefore, enumerable.
For user-defined objects in ES3 (and only user-defined objects),
propertyIsEnumerable
is equivalent to hasOwnProperty. Of course, IE will still exhibit the DontEnum bug
which is exposed in propertyIsEnumerable.
var x = { name : "Garrett" ,bench: 365 ,height : 73 ,weight : 215 ,toString : function() { return "not strong enough, not lean enough."; } }; var s = ""; // For any value of 's', this must always be true. var alwaysTrueExceptIE = g.hasOwnProperty( s ) == g.propertyIsEnumerable( s );
Not many authors use propertyIsEnumerable. I believe that it hasn't gotten widespread usage for two reasons:
There aren't many other uses of propertyIsEnumerable
in production code (excepting the anomalous YUI connection manager).
Changing propertyIsEnumerable in the spec appears safe.
The other proposed change to propertyIsEnumerable
is to have a second parameter to accept a boolean to set the DontEnum attribute. Although access
to the DontEnum attribute is necessary, the approach separates properties from property attributes.
Attributes are like modifiers.
Fix propertyIsEnumerable
The method propertyIsEnumerable should be renamed to isPropertyEnumerable, just like
it has been in Flash.
This method should check the prototype chain. This would allow for four possibilities of
r[ p ], when used with hasOwnProperty
propertyIsEnumerable?I leave a challenge to the reader to solve this problem cross browser:
Replace Object.prototype.propertyIsEnumerable when Safari 2 becomes nearly obsolete.
Since Safari 2 does not have Object.prototype.propertyIsEnumerable; adding
it to Object.prototype would cause it to be enumerated by a for in loop.
This would be disastrous.
DontEnum bug.
Getting the correct result for an object's constructor property would be a nice-to-have.
Array.prototype.
The patch should return false for things that should be enumerable,
such as JavaScript 1.6 Array.prototype.some.
There are a few approaches that we could consider:
DontEnum are usually native code.
DontEnum,
return false. Otherwise, return true.
propertyIsEnumerable. Not surprisingly, this is what most programmers do.
Checking to see if it's a native function won't solve the problem. Here's why:
toFixed example for more details. This is clearly explained in
ECMAScript's internal [[put]] method (§8.6.2.2).
toString can be user-defined. This is a perfectly
valid use-case. The effect this has is that a non-native function's toString
might be invalid code. For example:
function Widget(){} Widget.toString = function() { return "[object Widget]"; };
Don't rely on toString
myObj.sort = Array.prototype.sort
would result in myObj having an enumerable sort property.
While uncommon, it is perfectly valid to borrow Array's generic sort method.
/** Native code is never returned; instead, we always * get a string that could never be compilable, and would * cause a parser error. */ Function.isNative = function(f) { if(typeof f != "function") return false; try { new Function( f.toString() ); } catch(syntaxError) { return true; } return false; };
This might seem useful, but even if it were reliable (it isn't), it would
not return a property's DontEnum flag.
Host objects may also implement the DontEnum flag.
Next in this tutorial: Modifying Property Values