Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

How to JavaScript - Using defineProperty() and defineProperties()

4.38/5 (4 votes)
15 Oct 2017CPOL2 min read 9K  
JavaScript Design patterns - The Constructor Pattern

Introduction

In this article, I would like to explain how to use Object.defineProperty() and Object.defineProperties() methods. These two methods define new or modify existing properties directly on an object, returning the object (Visit MDN, which has an excellent introduction to them).

Creating an Object

If you consider an OOP JavaScript world, almost everything is an object. When it comes to object creation, I used to use one of the following three methods:

JavaScript
var beautifulObject = {};

// OR
var beautifulObject = Object.create( Object.prototype );

//OR
var beautifulObject = new Object();

Defining Object Property

Interestingly, there are four ways to assign keys and values to the object.

  1. Dot Syntax
  2. Square Bracket Syntax
  3. Object.defineProperty()
  4. Object.defineProperties()

A simple example of Dot syntax and Square Bracket syntax for assigning and accessing the object property:

JavaScript
// Dot Syntax
// Assignment
beautifulObject.beautifulProperty = "It is a beautiful property";
// Accessing
var prop = beautifulObject.beautifulProperty;

// Square Bracket syntax
// Assignment
beautifulObject["beautifulProperty"] = "It is a beautiful property";
// Accessing
var prop = beautifulObject["beautifulProperty"];

In the above examples, we do not control the property descriptor. That means it uses the default descriptor behaviour. Object property can be writable, re-configurable and enumerable. If we need control over all these, then we need to define the property using defineProperty() or defineProperties().

A simple example for defining object property with defineProperty():

JavaScript
var person = new Object(Object.prototype);

Object.defineProperty(person, "beautifulProperty", {
    value :  "It is a beautiful property",
    writable : false,    // readonly
    enumerable : false,  // not enumerable property
    configurable : false // do not allow re-configure the peroperty
});

console.log(person); 
// logs {beautifulProperty : "It is a beautiful property"}

When we want to define multiple properties with the descriptor, then we need to use defineProperties():

C#
var person = new Object(Object.prototype); 
var country = "India";

Object.defineProperties(person, {
    "gender" : {
        value : "male",
        writable : true,
        enumerable : true,
        configurable : false
    },
    "name" : {
        value : "Vinnie",
        writable : true,
        enumerable : true,
        configurable : false
    },
    "dob" : {
        value : "dd-MMM-YYYY",
        writable : true,
        enumerable : true,
        configurable : false
    },
    "country" : {
        // Lets user get/set accessors here
        // Please note using value and writable descriptor throws error when get/set is used 
        enumerable : true,
        get : function () {
            return country;
        },
        set : function (newCountry) {
            country = newCountry;
        }
    }
});

console.log(person);
// logs {gender: "male", name:"Vinnie", dob:"dd-MMM-YYYY", Country: [Getter/Setter]}

Now you might be wondering what is the use case of this design pattern. Well, with this constructor design pattern, it is very easy to achieve inheritance.

Say, I have a person object created above. If we need to create an object called a programmer and inherit the person properties, we can achieve like below:

JavaScript
var programmer = Object.create(person);
Object.defineProperty(programmer, "competency", {
    value : "JavaScript",
    writable : true,
    enumerable : true,
    configurable : true
});

console.log(programmer );
// logs {gender: "male", name:"Vinnie", dob:"dd-MMM-YYYY", 
// Country: [Getter/Setter], competency:"JavaScript"}

The programmer object inherits all the properties of the person.

Conclusion

Whenever we need to make an object property to be read-only or non-enumerable, Object.defineProperty() is very useful. With the enumerable descriptor, an object can, in some ways, simulate pseudo-private fields. Inheritance concept becomes painless.

References and Learning

History

  • 2017-Oct-14: First published

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)