Some notes on enumerable and non-enumerable properties in JavaScript
In Javascript enumerable properties are all those which can be iterated with a for…in
loop.
Every property has an attribute called. If that is set to true, the property is enumerable, if the attribute is set to false, the property is non-enumerable. When iterating through all properties of an object with a for…in
loop, the loop will only iterate over the properties whose enumerable attribute is set to true.
Properties such as length
, and valueOf
have an enumerable value of false by default, because it is assumed that you won’t want to iterate over those properties when iterating over all your other properties.
Find out whether a specific property is enumerable
In order to detect whether a property is enumerable you can call the propertyIsEnumerable(prop)
method on the object, passing the property to be checked.
let obj = {hello: 'world'}; console.log(obj.propertyIsEnumerable('hello')) //'true'
Making properties non-enumerable
To create your own non-enumerable properties, you can use the Object.defineProperty()
method:
Object.defineProperty(obj, ‘propName’, { value: ‘propValue, enumerable: false });
This will create a non-enumerable propName
property on obj
with the value ‘propValue’.
Retrieving all enumerable properties
To get all enumerable properties, both those found directly in the object and those inherited from the prototype chain, use the for…in
loop. Note, however, that object created from built-in constructors such as Object
, Array
or String
inherit non-enumerable properties from those built-in prototypes. So if you declare an an empty array and iterate over it with a for…in
, there will be nothing inside the loop since the object only inherited non-enumerable properties.
function Yello(){
this.prop = 'Hi';
}
var obj = [];
for (o in obj) {
//nothing inside the loop, since obj only inherited non-enumerable properties
console.log(o);
}
obj = {hello: 'world'};
for (o in obj) {
console.log(o); //['hello']
}
obj = new Yello();
obj.there = 'there';
for (o in obj) {
console.log(o); //['prop', 'there']
}
JSON.stringify()
works by iterating through all enumerable properties of an object (inherited and directly defined).
console.log(JSON.stringify(obj)); // {"prop":"Hi","there":"there"}
Retrieve enumerable properties found directly in an object
To retrieve the set of enumerable properties which were defined directly in an object (no inherited properties), call the keys()
method on the object.
let obj = {hello: 'world'};
Object.defineProperty(obj, 'propName', { value: 'propValue', enumerable: false });
console.log(Object.getOwnPropertyNames(obj)); // [ 'hello']
Only returns ‘hello’, since propName
is a non-enumerable property
Retrieve all enumerable and non-enumerable properties found directly in an object
To get all enumerable and non-enumerable properties which were defined directly in an object (no inherited properties) you can use the Object.getOwnPropertyNames()
class method.
let obj = {hello: 'world'};
Object.defineProperty(obj, 'propName', { value: 'propValue', enumerable: false });
console.log(Object.getOwnPropertyNames(obj)); // [ 'hello', 'propName' ]