How to use defineProperty method in JavaScript.

1 Introduction.

By default, Object properties created using assignment operator are mutable and enumrable using loop, it means that they can be updated or deleted from the Object.

Object.defineProperty allows us to pricisely define or modify existing property on an object and change those extra details of a property from their defaults. we will see exactly what are those extra details and how to change their default values later in this article.

Method Syntax-

Object.defineProperty(objectName, propertyName, descriptor)

Here

  • objectName is an object on which to define the property.
  • propertyName is the name of the property, it could be anything.
  • descriptor the descriptor object for the property.

Let's take an quick look how adding properties to an object using assignment (=) operator and Object.defineProperty looks like -

let obj = {} obj.property = "Some value"

writable, configurable and enumerable will be true if property is added using assignment operator.

For example, The above code snippet is equivalent to this Object.defineProperty method call.

let obj = {} Object.defineProperty(obj, "property", { value: "Some value", writable: true, configurable: true, enumerable: true, })

2. descriptor object keys

descriptor object has a few attributes to define the behaviour of a property, we will see how each attribute can be used to define the behaviour of object property.

2.a value

The value associated with the property, can be any JavaScript value eg. number, boolean, function etc. By default its value is undefined.

2.b writable

writable attribute is used to define whether the property value can be updated with an = (assignment) operator or not. By default its value is false.

Let's see how to add a read-only property to an JavaScript Object -

let batman = {} //lets add an favourite color property Object.defineProperty(batman, "favouriteColor", { value: "Black", writable: false, //value can't be updated enumerable: true, //iterable using loops })

Here we added a favouriteColor property to batman object, favouriteColor property value is "Black" and it can't be re-assigned or updated because descriptor.writable is false.

Let's try to update batman.favouriteColor from Black to Green.

batman.favouriteColor ='Green'; //throws error in strict mode console.log(batman.favouriteColor); //still prints 'Black'

In above code snippets, Trying to update a non-writable property operation failed and it didn't throw any error (unless you are using strict mode).

2.c configurable

configurable attribute is used to define whether the property descriptor can be updated and property can be deleted from the object or not. By default its value is false.

setting configurable to false means that -

  • the property can not be deleted from the object
  • its descriptor object can not be modified using Object.defineProperty.

Basically once you set configurable to false, the property (not its value) is freezed on the object, you can not set configurable to back to true for that property.

keep in mind that property value can be updated as long as writable is set to true. setting configurable to false does not prevent property value being updated.

We already made sure that batman.favouriteColor value is not changable by setting writable attribute to false, now let's make sure that no one can remove favouriteColor property from batman object by setting configurable to false.

Object.defineProperty(batman, "favouriteColor", { value: "Black", writable: false, //value can't be updated configurable: false, enumerable: true, //iterable using loops })

If property already exist on the object, Object.defineProperty will update the existing property (only if configurable is set to true);

Now, Trying to delete the favouriteColor property from the batman object using delete operator will return false.

delete batman.favouriteColor //returns false console.log(batman) // { favouriteColor: 'Black' }

Once configurable is set to false, you can't -

  • Delete the key from the object , trying to do so will not throw an error
  • Set configurable to true for that property, trying to do so will throw an error
  • Change enumerable property value

However, as i've already mentioned that property value can be updated (using . or [] notation ) as long as writable is set to true. setting configurable to false does not prevent property value being updated.

2.d enumerable:

enumerable attribute controls whether the property will show up or not during enumeration of the properties using for..in loops.

Sometimes you don't want certain properties to show up while iterating over the object keys. Let's add an speak method to batman object -

function speak() { console.log("I'm Batmannn") } //let's add it to the batman object batman.speak = speak console.log(batman) //{ favouriteColor: 'Black', speak: [Function: speak] }

Let's try to loop over the batman object -

for (let prop in batman) { console.log(prop) } //favouriteColor //speak

But what if we don't want speak to be accessible using loop? well you can use enumerable property to hide speak property from loops. By default enumerable value is false.

Let's hide speak property from for..in loop.

Object.defineProperty(batman, "speak", { value: speak, writable: true, configurable: true, enumerable: false, //hidden from loop })

Now speak property won't show while iterating over batman object -

for (let prop in batman) { console.log(prop) } //favouriteColor

Property that has enumerable set to false -

  • will not show in for..in loop.
  • will not be serialized using JSON.stringify.
  • will not show up in an array returned by Object.keys(batman).
  • will not be picked up by Object.assign() or spread operator.
  • are accessible using . or [] notation.

You can check whether a property is enumerable or not by using propertyIsEnumerable function, it returns true if property is enumerable.

Conclusion

By default Object properties are mutable, but sometimes you may want to change their default behaviour to achieve the objective. In that case it's good to have an idea about Object.defineProperty method and how it works.

Highly recommend to visit these links because there is a lot more to know about Object.defineProperty -

Say Hi on twitter and email

Designed and developed by Gulam Hussain.

Built with Gatsby. Hosted on Netlify.