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:
var beautifulObject = {};
var beautifulObject = Object.create( Object.prototype );
var beautifulObject = new Object();
Defining Object Property
Interestingly, there are four ways to assign keys and values to the object.
Dot Syntax
Square Bracket Syntax
Object.defineProperty()
Object.defineProperties()
A simple example of Dot syntax and Square Bracket syntax for assigning and accessing the object property:
beautifulObject.beautifulProperty = "It is a beautiful property";
var prop = beautifulObject.beautifulProperty;
beautifulObject["beautifulProperty"] = "It is a beautiful property";
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()
:
var person = new Object(Object.prototype);
Object.defineProperty(person, "beautifulProperty", {
value : "It is a beautiful property",
writable : false,
enumerable : false,
configurable : false
});
console.log(person);
When we want to define multiple properties with the descriptor, then we need to use defineProperties()
:
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" : {
enumerable : true,
get : function () {
return country;
},
set : function (newCountry) {
country = newCountry;
}
}
});
console.log(person);
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:
var programmer = Object.create(person);
Object.defineProperty(programmer, "competency", {
value : "JavaScript",
writable : true,
enumerable : true,
configurable : true
});
console.log(programmer );
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