Javascript Tutorial
Javascript Tutorial Introduction to Javascript JavaScript Code Editors & IDE JavaScript Hello World Example Javascript Syntax and Rules syntax_rules javascript_identifiers JavaScript Keywords & Reserved Words javascript_variables JavaScript Const JavaScript let vs var vs const Data Types in JavaScript JavaScript String Template Literals & String interpolation in JavaScript Tagged Templates in JavaScript String to Number in JavaScript Number Data Type in JavaScript NaN in JavaScript JavaScript Number Min & Max & Safe Values JavaScript EPSILON & Floating point precision Infinity in JavaScript JavaScript Bigint BigInt Vs Number in JavaScript Boolean Data Type in JavaScript Undefined in JavaScript Null in JavaScript Null vs Undefined in JavaScript JavaScript Operators Arithmetic Operators in JavaScript Unary plus & minus operators in JavaScript Increment & Decrement Operators in JavaScript Comparison or Relational operators in JavaScript Strict Equality (==) Loose Equality (===) in JavaScript Ternary Conditional Operator in JavaScript Logical Operators in JavaScript Bitwise Operators in JavaScript Assignment Operators in JavaScript Nullish Coalescing Operator in JavaScript Comma Operator in JavaScript Typeof JavaScript Operator Precedence in JavaScript JavaScript if, else & nested if statement Switch Statement in JavaScript While & Do While Loops in JavaScript For Loop in JavaScript Break statement in JavaScript Continue Statement in JavaScript Arrays in JavaScript Array Constructor in Javascript Sparse Array Vs Dense Array in JavaScript How to merge Arrays in JavaScript Array Methods in JavaScript Functions in JavaScript Function Parameters & Arguments in JavaScript JavaScript Default Parameters Pass by Value and Pass by Reference in Javascript Function Expression in Javascript Nested Functions in JavaScript Immediately-invoked Function Expressions (IIFE) JavaScript Callback Functions Arrow Functions in JavaScript Arguments Object In JavaScript Rest Parameters in JavaScript Objects in Javascript Create Objects in JavaScript JavaScript Object Properties Computed Property Names in JavaScript Object Literal in JavaScript Constructor Function & New Operator in JavaScript Delete Operator in JavaScript hasOwnProperty in JavaScript Using Getters and Setters in Javascript DefineProperty in JavaScript JavaScript Property Descriptors Enumerable, Writable & Configurable Object Destructuring in JavaScript Variable Scope in JavaScript Hoisting in JavaScript Lexical Scope & Closures in JavaScript This in JavaScript Global Object, Window & Globalthis in JavaScript Call function in Javascript Prototype In Javascript Prototype Inheritance in JavaScript Instanceof Operator in JavaScript Spread Operator in JavaScript

JavaScript Property Descriptors Enumerable, Writable & Configurable

Javascript Property Descriptors allow us to configure a JavaScript Property using the flags like enumerable, writable & configurable. We can read the Property Descriptors using the getOwnPropertyDescriptor and alter them using the DefineProperty.

What is Property Descriptors

Property Descriptors hold the configurations of an object’s property.

We can create a JavaScript object in many ways. Every property that we add to the object automatically gets its own Property descriptor. A property descriptor is a simple object and contains the metadata or information about the Property.

There are two types of Properties in JavaScript. Data Properties & Accessor Properties.

Data Properties maps to a value (i.e. primitive value, object, or function). Accessor Properties maps to getter & Setter methods. Each of these Property types also has its own Property Descriptors. Hence are two types of Property Descriptors.

  1. Data Descriptors ( for Data Properties)
  2. Accessor Descriptors (for getter & setter or Accessor Properties)

A JavaScript Property can have only one of the Descriptors. It cannot have both Descriptors.

Data Descriptors

Data Descriptors is for Data Properties. It contains the following fields

  • value
  • Writable
  • Enumerable
  • configurable

When we create a new object using the Object literal Syntax or any other method, JavaScript adds the descriptor for each Property. By default, it creates the property Writable, Enumerable & configurable set to true. The Value property is set to the value of the Property.

Accessor Descriptors

Accessor Descriptors is for Accessor Properties. It contains the following fields

  • set
  • get
  • Enumerable
  • configurable

When we create a getter & setter property using the Object literal Syntax JavaScript adds this descriptor to the property. By default, it creates the descriptor with Enumerable & configurable set to true. The get & set mapped to the getter & setter functions.

        
 const person = {
  _name: "",
  get name() {
    return this._name;
  },
  set name(value) {
    this._name = value;
  },
};
 
                
        
    

getOwnPropertyDescriptor

You can read the Property Descriptor of any property using the getOwnPropertyDescriptor method.

Syntax

        
Object.getOwnPropertyDescriptor(obj, prop)
 
                
        
    

Where

obj is the object in which to look for the property..

prop name of the property whose description we want to retrieve

The following is a person object with name (accessor property) & age (data property) properties. We use the getOwnPropertyDescriptor to retrieve their descriptors

        
const person = {
  _name: "",
  
  get name() {
    return this._name;
  },
  set name(value) {
    this._name = value;
  },
 
  age:30
};
 
 
 
console.log(Object.getOwnPropertyDescriptor(person,'name'))
 
console.log(Object.getOwnPropertyDescriptor(person,'age'))
 
                
        
    

You can see from the output that the accessor property descriptor does not have writable & value property. The data property descriptor does not have get & set property

Useful References

Also, note that configurable, enumerable & writable are set to true

Setting the Descriptors

We can modify the object returned by the getOwnPropertyDescriptor , but it will not change the descriptor of the original property

To change the descriptor of a Property, we can use the defineProperty or defineProperties method

defineProperty

The defineProperty adds a new property or modifies an existing property. It returns the object.

Syntax

To change the descriptor of a Property, we can use the defineProperty or defineProperties method

        
Object.defineProperty(obj, prop, descriptor)
 
                
        
    

Where

obj in which to look for the property.

propis the name of the property whose description we want to add or modify.

descriptor for the property that wants to add or modify

For a new property, If we do not provide any values for Writable, Enumerable & configurable, then they are set to false. The value is set to undefined.

Example

The following code creates an empty person object. We then add the _name & age data properties & name getter & setter method using the defineProperty method.

        
const person = {};
 
 Object.defineProperty(person, "_name", {
   value: "",
   writable: true,
   configurable: true,
   enumerable: true,
 });
  
 Object.defineProperty(person, "name", {
   get() {
     return this._name;
   },
   set(value) {
     this._name = value;
   },
   configurable: true,
   enumerable: true,
 });
  
 Object.defineProperty(person, "age", {
   value: "30",
   writable: true,
   configurable: true,
   enumerable: true,
 });
 
                
        
    

But if the property already exists, the existing values are overwritten only if the values are provided.

        
const person = {
    age:10
};
 
console.log(Object.getOwnPropertyDescriptor(person,'age'))
//{value: 10, writable: true, enumerable: true, configurable: true}
 
//Does not affect as the descriptoris empty
Object.defineProperty(person, "age", {});
 
console.log(Object.getOwnPropertyDescriptor(person,'age'))
//{value: 10, writable: true, enumerable: true, configurable: true}
 
                                    
                                

defineProperties

It is similar to defineProperty but allows us to add or modify multiple properties

Syntax

        
Object.defineProperties(obj, props)
 
                                    
                                

Where

Syntax

It is similar to defineProperty but allows us to add or modify multiple properties

obj in which to look for the property.

props is an object whose each property must be a descriptor (either a data descriptor or an accessor descriptor). The name of the key becomes the property name.

        
const person = {};
 
 obj= {
   _name : { value: "",    writable: true,  configurable: true,   enumerable: true,  },
  
   name  : { get() {  return this._name;   },
             set(value) {     this._name = value; },  
             configurable: true,   enumerable: true,  },
  
   age   : { value: "30",  writable: true,  configurable: true,   enumerable: true,  }
 }
  
  
 Object.defineProperties(person,obj);
  
 console.log(person)
 
                                    
                                

Value

This Property of the Property Descriptor holds the Value of the Property.

                            
const person = {};
 
//Creating new property. note that writable is set true.
Object.defineProperty(person, "age", { value:10, writable:true});
console.log(person.age)    //10
 
 
//No values is provided. does not overwrite
Object.defineProperty(person, "age", {});
console.log(person.age)  //10
 
 
//Sets the age as 30
Object.defineProperty(person, "age", { value:30});
console.log(person.age)  //30
 
person.age=40
console.log(person.age)   //40
 
  
    
        
    

Writable

Writable determines whether you can modify the value of the property or not. A false value makes property read-only.

The following code creates the age property with the value of 10 with writable as false.

Assigning a new value of 20 will fail. If you have use strict enabled, then JavaScript throws an error else it will fail silently.

        
"use strict"
const person = {};

//Creating new property. 
Object.defineProperty(person, "age", { value:10,writable:false, configurable:true,enumerable:true});
console.log(person.age)    //10
 
//
person.age=20
//
//Cannot assign to read only property 'age' of object '#<Object>'//

//Remove use strict
//Error is thrown only when using use strict. else fails silently
 
console.log(person.age)    //10




In this example, we revert back the writable:false to writable:true. Now you can modify the property.

        
const person = {};
 
//Creating new property. 
Object.defineProperty(person, "age", { value:10,writable:false, configurable:true,enumerable:true});
console.log(person.age)    //10
 
person.age=20    //fails
console.log(person.age)    //10
 
 
//Makng Writable true again
 
Object.defineProperty(person, "age", { writable:true});
person.age=20              //works now
console.log(person.age)    //20




Enumerable

An enumerable flag determines if we can view the property using the for..in loop or Object.keys() method.

The person object in the following example has three properties. Both for..in loop & Object.keys() returns all three because enumerable by default set to true

        
const person = {
    prop1:"one",
    prop2:"two",
    prop3:"three"
 
};
 
console.log(Object.keys(person))   //["prop1", "prop2", "prop3"]
 
 
for (const key in person) {
    console.log(key)
}
 
//prop1
//prop2
//prop3
 
Object.defineProperty(person, "prop2", { enumerable:false});
 
console.log(Object.keys(person))   //["prop1", "prop3"]
 
for (const key in person) {
    console.log(key)
}
 
//prop1
//prop3
  
 
 
    
        
    

We modify the prop2 and set its enumerable to false. Now both for..in loop & Object.keys() will not return prop2

Configurable

Configurable property if true allows us to modify the writable & enumerable property of an object. It also allows us to delete the property. But if it is set to false, then you cannot change the value of enumerable neither you can delete the property. It allows changing the writable from true to false but not from false to true. Once you set configurable as false, you cannot set it true again.

The following code makes the firstName non-configurable. Now you cannot modify its enumerable flag.

                        
"use strict"
 
const person = {
    firstName:"Bill",
    lastName:"Gates",
};
 
 
Object.defineProperty(person, "firstName", { configurable:false});
 
Object.defineProperty(person, "firstName", { enumerable:false});
//Uncaught TypeError: Cannot redefine property: firstName    

                                    
                                

But you can change writable from true to false. But not from false to true.

                        
"use strict"
 
const person = {
    firstName:"Bill",
    lastName:"Gates",
};
 
 
Object.defineProperty(person, "firstName", { configurable:false});
 
 
//No Error here. You can change true to false
Object.defineProperty(person, "firstName", { writable:false});
 
 
//But cannot make it writable again
Object.defineProperty(person, "firstName", { writable:true});
//Uncaught TypeError: Cannot redefine property: firstName
                                    
                                

Non-configurable properties cannot be deleted.

                        
                        "use strict"
 
 const person = {
     firstName:"Bill",
     lastName:"Gates",
 };
  
  
 Object.defineProperty(person, "firstName", { configurable:false});
  
 delete person.lastName   //deleted
 console.log(person)  
  
 //cannot delete
 delete person.firstName  
 //Uncaught TypeError: Cannot delete property 'firstName' of #<Object>
                                    
                                

Setting configurable to false is a one-way street. You cannot set it to true again

                        
"use strict"
 
const person = {
    firstName:"Bill",
    lastName:"Gates",
};
 
 
Object.defineProperty(person, "firstName", { configurable:false});
 
 
 
Object.defineProperty(person, "firstName", { configurable:true});
//Uncaught TypeError: Cannot redefine property: firstName
                                    
                                

Get & Set

The Get & Set property descriptors are mapped to the Getter and Setter functions. The getter & setter methods are known as accessor properties in JavaScript. They look like normal properties but are actually functions mapped to a Property

        
const person = {};
 
obj= {
  _name : { value: "",    writable: true,  configurable: true,   enumerable: true,  },
 
  name  : { get() {  return this._name;   },
            set(value) {     this._name = value; },  
            configurable: true,   enumerable: true,  },
}




Read More

  1. JavaScript Tutorial
  2. Objects in JavaScript
  3. Create Objects in JavaScript
  4. Object Properties
  5. Computed Property Names
  6. Object Literal
  7. Constructor functions
  8. DefineProperty
  9. Property Descriptors Enumerable, Writable & Configurable
  10. Object Destructuring