JavaScript Object Property Flags and Descriptors

— Modifying objects with descriptors and writable, enumerable and configurable flags.

E.Y.
4 min readDec 1, 2020
Photo by Philippine FITAMANT on Unsplash

In this blog we are going to look into manipulating Object and its properties in JavaScript, referencing its writable, enumerable and configurable flags.

But first, let’s revisit the Object concept.

The Object class represents one of JavaScript's data types. It is used to store various keyed collections and more complex entities. Objects can be created using the Object() constructor (new Object(), Object.create()) or the object initialiser / literal syntax.

Normally, there are 4 types of property/method to think about:

  • Those defined inside a constructor function that are given to object instances. Like the name property below.
class Person {
constructor(name) {
this.name = name;
}
this.age = age
}
Person.prototype.greeting = `Hi! I'm ${this.name}`
  • Those defined directly on the constructor themselves, that are available only on the constructor, known as static properties/methods. Like the age above.
  • Those defined on a constructor’s prototype, which are inherited by all instances and inheriting object classes. Any member defined on a Constructor’s prototype property. Like the greeting method above.
  • Those available on an object instance. For example me = new Person(); me.career = "teacher"; .

All the properties above are defined as “key-value” pairs. But there are some hidden attributes on them that are default if not set but have great power underneath.

Object properties, besides a value, have flags.

Enumerable

Enumerable flag defines if the property is enumerable and show up in for…in loops unless the property’s key is a Symbol. If it’s set to false then it also won’t be picked by Object.assign() or spread operator.

var o = {};Object.defineProperty(o, 'a', {
value: 1,
enumerable: true
});
Object.defineProperty(o, 'b', {
value: 2,
enumerable: false
});
for (var i in o) {
console.log(i);
} //'a'
Object.keys(o); // ['a']

Writable

When the writable property attribute is set to false, the property is said to be “non-writable”. It cannot be reassigned.

'use strict'
var o = {};
Object.defineProperty(o, 'a', {
value: 37,
writable: false
});
console.log(o.a); // 37
o.a = 25; // throws a TypeError

Configurable

The configurable attribute controls at the same time whether the property can be deleted and whether its attributes (other than value and writable) can be changed.

  • Can’t delete the property
  • Can’t change configurable .
  • Can’t change enumerable .
  • Can’t change writable: false to true (works the other way around).
  • Can’t change getter/setter (but can assign them if absent).
var o = {};Object.defineProperty(o, 'a', {
get() { return 1; },
configurable: false
});

Object.defineProperty(o, 'a', {
set() {}
}); // throws a TypeError (set was undefined previously)
Object.defineProperty(o, 'a', {
get() { return 1; }
}); // throws a TypeError
// (even though the new get does exactly the same thing)
Object.defineProperty(o, 'a', {
value: 12
}); // throws a TypeError // ('value' can be changed when 'configurable' is false but not in this case due to 'get' accessor)

To define the object property in a formal way (instead of using assignment operator) we can use the below method.

Object.defineProperty(obj, prop, descriptor)

The static method Object.defineProperty() defines a new property directly on an object, or modifies an existing property on an object, and returns the object.

const object1 = {};Object.defineProperty(object1, ‘property1’, {
value: 42,
writable: false
});

You can see the 3rd argument is descriptor. This is where all the 3 flags we mentioned earlier come into play. Property descriptors present in objects come in two types: data descriptors and accessor descriptors. A descriptor must be one of these two, it cannot be both.

  • By default, both types have configurable: false and enumerable: false .

But there are something specific to the kind.

  • A data descriptor is a property that has a value field, defaults to undefined , and a writable field defaults to false that indicates if the property can be reassigned.
  • An accessor descriptor is a property described by a getter-setter pair of functions. get is a function which serves as a getter for the property defaults to undefined. set is a function which serves as a setter for the property, defaults toundefined .

Note that the flags have different values with different ways of adding properties and default values.

var o = {};o.a = 1;
// is equivalent to:
Object.defineProperty(o, 'a', {
value: 1,
writable: true,
configurable: true,
enumerable: true

});
Object.defineProperty(o, 'a', { value: 1 });
// is equivalent to:
Object.defineProperty(o, 'a', {
value: 1,
writable: false,
configurable: false,
enumerable: false

});

That’s so much of it today!

Next blog we will look at the different methods to manipulate Objects.

Happy Reading!

--

--