Property descriptors in JavaScript

In JavaScript the most common way of creating properties on objects is by dot notation 0bj.property = ‘value’ or using brackets notation obj[property] = ‘value’.

It might be surprising to learn that a property is not just a name and a value. Every property has a property descriptor.

var person = { name : ‘Faiz’, country : ‘US’} 
console.log(Object.getOwnPropertyDescriptor(person, ‘name’)); 
Output : 
{
“value”: “Faiz”,
“writable”: true,
“enumerable”: true,
“configurable”: true
}

When I created a person object with name as the key and faiz it’s value. JavaScript created property descriptor for name property of person object. In addition name property having a value it also has writable, enumerable, and configurable attributes. All these are set to true by default, unless we choose to give them other value while creating property on object or even after the property is created. Let’s now understand what each attribute corresponds to.

Writable: The writable attribute defines whether the property’s value can be changed from initial value.

Object.defineProperty(person, 'name', {'writable' : false});
person.name = 'John'; // The name will not be changed
console.log(person.name);
//output:   
"faiz"

Enumerable: The for .. in loop can be used to get the properties of an object. By default, properties on an object have enumerable attribute set to true, which means we can loop over them using the for .. in loop. But if we make enumerable false on any property then even if we loop over the object, the property will not be returned in the loop.
Note : Even if the property’s enumerable attribute is set to false we can still look at the property in the object. But we cannot enumerate it or see it in Object.keys.

for (let key in person) { console.log(key); }
// output : name country
Object.defineProperty(person, 'name', {'enumerable' : false});
for (let key in person) { console.log(key); } 
// output : country
Object.defineProperty(person, 'name', {'enumerable' : true});
for (let key in person) { console.log(key); }
// output : name country

Configurable: The configurable property if set to false will lock down the property’s attributes from being changed. We cannot set the configurable to true anymore or we cannot change the enumerable attribute. We can however change it’s writable attribute. It also prevents the property from being deleted from the object.

// changing enumerable property to false
Object.defineProperty(person, 'name', {'enumerable' : false});
// Setting configurable to false. We can no longer change 
// configurable and enumerable attributes.
Object.defineProperty(person, 'name', {'configurable' : false});
// Changing enumerable to true will now result in error
Object.defineProperty(person, 'name', {'enumerable' : true});
//output : TypeError: Cannot redefine property
Object.defineProperty(person, 'name', {'configurable' : true});
//output : TypeError: Cannot redefine property

Setting Attributes while creating properties on objects : We have seen how we can change attributes after the property was created using dot or bracket notation. We can also set the attributes when we create the properties by using Object.defineProperty. We give a value to the property and set the attributes to true/false.

Object.defineProperty(person, 'state', {'value' : 'CA', 'writable' : true, 'enumerable' : false, 'configurable' : true});
console.log(Object.getOwnPropertyDescriptor(person, 'state'));
Output:
{
value: "CA",
writable: true,
enumerable: false,
configurable: true
}

Continue reading — Part 2