Enumerable Properties in JavaScript
Enumerable properties are properties whose internal enumerable flag set to true. Enumerable simply means "countable", and with JavaScript objects, enumerable properties are those we are typically interested in when iterating over properties. This designation is required because JavaScript objects, as you may know, have many additional properties, like __proto__
and constructor
, that we typically want to include when retrieving properties.
Posted in these interests:
Before digging in, let's learn how to check if a property is enumerable. To do this we can use Object.prototype.propertyIsEnumerable()
.
Hang with me here, but JavaScript objects have a property called propertyIsEnumerable
, which, as you might guess, checks to see if a property is enumerable. For fun, let's check if the propertyIsEnumerable
property is an enumerable property :)
let obj = {}
obj.propertyIsEnumerable('propertyIsEnumerable') // => false
Nope!
The above example also demonstrates the usage. Let's see a few more examples:
let obj = {
firstname: 'Harry',
lastname: 'Potter'
}
obj.propertyIsEnumerable('constructor') // => false
obj.propertyIsEnumerable('__proto__') // => false
obj.propertyIsEnumerable('firstname') // => true
obj.propertyIsEnumerable('lastname') // => true
Now that we know how to check if a property is enumerable, let's learn how to define enumerable properties. To do this we're going to use Object.defineProperties
and Object.defineProperty
.
Object.defineProperty
First, let's take an existing, empty object.
let obj = {};
Typically, we could define properties like this:
obj.someProp = 'someValue';
But if we wanted to specify internal flags (like enumerable
) for this property, we can do so using defineProperty
.
Object.defineProperty(obj, 'someProp', {
value: 'someValue',
enumerable: true
});
Now, the above example is unnecessary. It accomplished the same thing as normal property assignment because the default value for enumerable
is true
anyways. But I wanted to show how the enumerable
property would be set, or unset.
Let's create a property that is not enumerable.
Object.defineProperty(obj, 'nonEnumerableProp', {
value: 'someValue',
enumerable: false
});
Now, let's prove our work:
obj.propertyIsEnumerable('someProp') // => true
obj.propertyIsEnumerable('nonEnumerableProp') // => false
Object.defineProperties
We can also define more than one property at a time using defineProperties
. Notice it takes a different set of arguments.
Object.defineProperties(obj, {
'someProp': {
value: 'someValue',
enumerable: true
},
'nonEnumerableProp': {
value: 'someValue',
enumerable: false
}
});
One of the most important reasons to understand property enumerability is to understand how to access properties during iteration. Since JavaScript objects are complicated and have many different kinds of properties, we don't always want to access every property when looping over properties.
We've written an in-depth guide on iterating over JavaScript object properties and values, but I will provide an overview here as well.
A note on inherited properties
Another important characteristic of a property is whether or not it is an own property, meaning it belongs to the object directly, or whether it is inherited, meaning it exists on the objects prototype chain.
Take a look at the following table, to see how to access properties with various characteristics.
Enumerable | All (including non-enumerable) | |
---|---|---|
Own | Object.keys |
Object.getOwnPropertyNames |
All (including inherited) | for...in |