Enumerability and ownership of properties
Enumerable properties are those properties whose internal [[Enumerable]] flag is set to true, which is the default for properties created via simple assignment or via a property initializer (properties defined via Object.defineProperty and such default [[Enumerable]] to false). Enumerable properties show up in for...in loops unless the property's name is a Symbol. Ownership of properties is determined by whether the property belongs to the object directly and not to its prototype chain. Properties of an object can also be retrieved in total. There are a number of built-in means of detecting, iterating/enumerating, and retrieving object properties, with the chart showing which are available. Some sample code follows which demonstrates how to obtain the missing categories.
Property enumerability and ownership - built-in methods of detection, retrieval, and iteration
Functionality |
Own object |
Own object and its prototype chain |
Prototype chain only |
Detection |
|
Not available without extra code |
Not available without extra code |
Retrieval |
|
Not available without extra code |
Not available without extra code |
Iteration |
|
Enumerable |
Nonenumerable |
Enumerable and Nonenumerable |
for..in |
Not available without extra code |
Not available without extra code |
|
Not available without extra code |
Obtaining properties by enumerability/ownership
Note that this is not the most efficient algorithm for all cases, but useful for a quick demonstration.
- Detection can occur by
SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1
- Iteration can occur by
SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {});
(or use filter()
, map()
, etc.)
var SimplePropertyRetriever = {
getOwnEnumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerable);
},
getOwnNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._notEnumerable);
},
getOwnEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable);
},
getPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerable);
},
getPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._notEnumerable);
},
getPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
},
getOwnAndPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerable);
},
getOwnAndPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._notEnumerable);
},
getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
},
_enumerable : function (obj, prop) {
return obj.propertyIsEnumerable(prop);
},
_notEnumerable : function (obj, prop) {
return !obj.propertyIsEnumerable(prop);
},
_enumerableAndNotEnumerable : function (obj, prop) {
return true;
},
_getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
var props = [];
do {
if (iterateSelfBool) {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
props.push(prop);
}
});
}
if (!iteratePrototypeBool) {
break;
}
iterateSelfBool = true;
} while (obj = Object.getPrototypeOf(obj));
return props;
}
};
Detection Table
|
in |
for..in |
hasOwnProperty |
propertyIsEnumerable |
in Object.keys |
in Object.getOwnPropertyNames |
in Object.getOwnPropertyDescriptors |
Enumerable |
true |
true |
true |
true |
true |
true |
true |
Nonenumerable |
true |
false |
true |
false |
false |
true |
true |
Inherited Enumerable |
true |
true |
false |
false |
false |
false |
false |
Inherited Nonenumerable |
true |
false |
false |
false |
false |
false |
false |
Account for Symbols keys |
true |
false |
true |
true |
false |
false |
true |
See also