JavaScript: Object.defineProperty

Dornhoth
Dornhoth
May 14 · 4 min read
Photo by davisco on Unsplash

An object in JavaScript is a collection of properties, a property being the association of a key and a value. Creating an object is pretty straightforward:

const person = {
name: 'Max',
age: 23,
};

To define a new property in an existing object all you need to do is to assign it a value:

person.gender = 'Male';

But there is another way, a bit less known, of defining properties: Object.defineProperty. It expects three parameters: the object, the property name and a descriptor:

Object.defineProperty(object, propertyName, descriptor);

The descriptor, as its name indicates, is an object describing the property to be, as we are going to see in the following examples. This syntax is generally longer, doesn’t feel as natural, but it can do things the classic assignment can’t.

Writable, Enumerable and Configurable

The gender property we assigned to the object person is

  1. writable
  2. enumerable
  3. configurable

The first point, writable, means that you can change the value of the property:

person.gender = 'Female';
console.log(person.gender); // Female

The second point, enumerable, means that the property shows up in enumerations of the object’s properties, for example in a for ... in ... loop:

for (const key in person) {
console.log(key); // name age gender
}

Finally, the property being configurable means that you can delete the property afterwards, or change its writable and enumerable parameters:

delete person.gender;
console.log(person.gender); // undefined

It is natural to us that properties behave this way, but they don’t have to. By default a property defined with Object.defineProperty isn’t writable, enumerable nor configurable.

Object.defineProperty(person, 'gender', {
value: 'Male',
});
// Non writable
person.gender = 'Female';
console.log(person.gender); // 'Male'
// Non enumerable
for (const key in person) {
console.log(key); // name age
}
// Non configurable
delete person.gender;
console.log(person.gender); // 'Male'

Using Object.defineProperty can therefore be a good alternative to a Proxy if your goal is to achieve something like this (if you have never heard of JavaScript proxies, this way).

Properties defined this way might by default not be writable, enumerable nor configurable but you can of course change it in the descriptor:

Object.defineProperty(person, 'gender', {
value: 'Male',
writable: true,
enumerable: true,
configurable: true,
});
// Writable
person.gender = 'Female';
console.log(person.gender); // 'Female'
// Enumerable
for (const key in person) {
console.log(key); // name age gender
}
// Configurable
delete person.gender;
console.log(person.gender); // undefined

Accessor Descriptor

In the previous example, we defined the property using data. We used the descriptor to give it a value and declare it writable, enumerable and configurable. Our descriptor was therefore a data descriptor. There is another way of defining a property using Object.defineProperty: accessor descriptors.

These descriptors have a get and a set methods in which you can respectively define how the property can be read and written.

let value = 'Male';
Object.defineProperty(person, 'gender', {
get: () => value,
set: (newValue) => value = newValue,
});
console.log(person.gender); // Male
person.gender = 'Female';
console.log(person.gender); // Female

By default, these methods return undefined. By not defining a set method, you would make your property non writable.

Object.defineProperty(person, 'gender', {
get: () => 'Male',
});
console.log(person.gender); // Male
person.gender = 'Female';
console.log(person.gender); // Male

Again, that could be a short and simple alternative to a Proxy if all you intend to do is make a property non writable.

Worth noting is that you can either use a data descriptor or an accessor descriptor, but you can’t mix both. Trying to do so would result in an error being thrown. An error is also thrown is you try to change the configuration of a non configurable property, but trying to write a non writable property doesn’t. It just doesn’t change the value.

Object.defineProperty is overkill in most common JavaScript situations. But it is a good, native, readable and easy to implement solution to monitor how your property is accessed in cases where you don’t want your property being writable, deletable or enumerable.

A note from the Plain English team

Did you know that we have four publications? Show some love by giving them a follow: JavaScript in Plain English, AI in Plain English, UX in Plain English, Python in Plain English — thank you and keep learning! We’ve also launched a YouTube and would love for you to support us by subscribing to our Plain English channel

And as always, Plain English wants to help promote good content. If you have an article that you would like to submit to any of our publications, send an email to submissions@plainenglish.io with your Medium username and what you are interested in writing about and we will get back to you!

JavaScript In Plain English

New articles every day.

Thanks to p.nut

Dornhoth

Written by

Dornhoth

JavaScript developer. I am writing about problems I came across at work, or stuff I am trying out in my free time. For those it might help.

JavaScript In Plain English

New articles every day.

Dornhoth

Written by

Dornhoth

JavaScript developer. I am writing about problems I came across at work, or stuff I am trying out in my free time. For those it might help.

JavaScript In Plain English

New articles every day.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store