Back to: JavaScript Tutorial For Beginners and Professionals
JavaScript Objects are Mutable
In this article, I am going to discuss JavaScript Objects are Mutable with Examples. Please read our previous article where we discussed Call by Value and Call by Reference in JavaScript with Examples.
JavaScript Objects are Mutable
In JavaScript, objects are mutable meaning their contents can be modified even when they are declared as const. so new properties can be added, and existing properties values can be altered (updated or deleted). The variable refers to an object whose reference cannot be changed.
Example to Understand JavaScript Objects are Mutable
<html> <head> <title>JavaScript Objects are Mutable example1</title> </head> <body> <script> const person = { name: 'John', age: 15, bloodgroup: 'A+', } console.log('Person object: ', person) //{name: 'John', age: 15,bloodgroup: 'A+'} //deleting age property of person object delete person.age person.bloodgroup = 'B+' console.log('Person object after altering: ', person) //{ name: 'John', bloodgroup: 'B+' } person = {}// TypeError: Assignment to constant variable. </script> </body> </html>
Output:
JavaScript Mutable VS Immutable Objects
As we have seen in JS, custom/user-defined objects that we create are generally mutable (whose value can be changed). So here comes a question how we can make objects immutable (that cannot be changed) or add immutability to JavaScript Objects?
The answer is this is possible by using the “Object.defineProperty()” method. That we have studied and seen its functionality in the Property flags and descriptors /Object properties configuration Tutorial. So, let’s investigate little more about “Object.defineProperty()” method.
As we understand what Mutability means, if an object is created, after its creation, its value or states can be changed or modified then it is called Mutable otherwise it’s Immutable.
Object.defineProperty() method is an in-built method provided by JavaScript used for doing two things:
- Adding a new property to an empty object
- Updating the existing property value of an object using a property descriptor
Syntax: Object.defineProperty(obj, propName, descriptor)
Parameters:
- Obj – It is an object name on which property is defined.
- propName – The name of the property or Symbol of the property to be defined or modified.
- descriptor – The descriptor for the property being modified or defined. It can be a data descriptor or accessor descriptor (property descriptor).
Return Value –– This defineProperty() method returns the object which is passed as the argument to the method.
Object.defineProperty() method can be invoked with the following options:
Object.defineProperty() method can be invoked with the following options: Object.defineProperty(obj, 'Propertyname', { value: valueOfTheProperty, writable: true, // if false, the property is read-only, and value cannot be change. configurable: true, // true means the property attribute can be modified and can be deleted enumerable: true // true means property can be enumerated using loop such as in a for..in loop });
Note: By default, the property added by using the Object.defineProperty() method are immutable (Objects whose value cannot be changed) and not enumerable (an object that cannot be counted and don’t show up when iterating using loop are called non-enumerable). In short, the property added by this method is not enumerable, not configurable, and not writable as defaults.
// not enumerable, not configurable, not writable as defaults. When no flags are provided
Object.defineProperty(obj, ‘propertykey’, descriptor);
When creating a property using Object.defineProperty() if there is no attribute specified in the object. This method will use their default values. That means Properties created using the method Object.defineProperty() have an enumerable flag set to false by default, a configurable flag set to false by default, and a writable flag set to false by default.
The question would be here why choose this method when we have an easy way by using the assignment operator (=)? Let us see why we need it. Generally, the properties are added using the assignment operator containing the below things. They are enumerable (an object that can be counted and show up during enumeration using a loop (for…in or object.keys() method on them) are called enumerable
They are Configurable (an object’s property values can be changed, or they can be deleted.) So, what this Object.defineProperty() method does is that it gives us the control to customize the object over the above things likewise default values get added using this method are not enumerable, not configurable, and not writable (immutable) by default.
Now let us investigate the 3rd parameter of the Object.defineProperty() method which is “descriptor” in detail. Property descriptors present in Object.defineProperty() come in two main varieties:
- Data Descriptors:
- Accessor Descriptors (property accessor):
Both data descriptors and accessor descriptors are objects. They share the below listed optional keys. The defaults value mentioned here are in the case when properties are defined using Object.defineProperty() without any parameters:
- Configurable: By default, it is false. When set to true that means the type of this property descriptor can be modified or updated later and the property can be deleted from the respective object.
- Enumerable: By default, it is false. When set to true that means this property can be counted and show up when iterating using a loop (for… in) are called enumerable or during enumeration of the properties. To check whether a property is enumerable or not, the function called propertyIsEnumerable() is used. It returns true if the object property is enumerable otherwise returns false.
Data Descriptors in JavaScript:
A data descriptor is a value of a property, which can or cannot be writable(modify).
Required fields: value or writable or both also
Optional fields: configurable, enumerable
Example:
// an object property added with defineProperty with a data property descriptor Object.defineProperty(objPerson, "age", { value: 10, writable: true, enumerable: false, configurable: false });
A Data Descriptor also has the following attributes:
- value: By default, it is undefined. It is the value of the property defined. The value can be any JavaScript value that is a number, string, function, object, etc.
- writable: By default, it is false. it is read-only. When set to true that means the value of the property can be changed by using the assignment operator (=) followed by the new value of a property.
Accessor Descriptors (property accessor) in JavaScript:
A data descriptor is a value of a property, which can or cannot be writable(modify). An accessor descriptor or property accessor is a property described by a getter-setter accessor combination of functions. A descriptor must be one of these two options: either getter or setter, it cannot be both.
Getter is for reading or fetching the property value whereas setter is for setting a new or modifying the existing value of a property.
Required fields: get or set or both
Optional fields: configurable, enumerable
Example:
//An object property added with defineProperty with an accessor property descriptor var oldValue =30; Object.defineProperty(objPerson, "carSpeed", { get: function () { return oldValue; }, set: function (newValue) { oldValue = newValue; }, enumerable: true, configurable: true });
An accessor descriptor/property accessor also has the following optional:
- get: By default, it is undefined. It is a get method that is a getter for the property, it makes the property read-only. This method returns a value of the property which means it is used for getting/fetching the property value. If no getter is provided it is undefined.
- set: By default, it is undefined. It is a set method that is a setter for the property, it makes the property writable. This method accepts a new value as an argument getting assigned to the property which means it is used for setting a new value or modifying the existing value of a property. If no setter is provided it is undefined.
If a property descriptor does not have value, writable, get, and set keys, it is considered a data descriptor. An exception is thrown If a property descriptor has both [value or writable] and [get or set] keys.
Now by using writable: false, and configurable: false, we essentially created a constant object property that cannot be changed, redefined, or deleted. Thus, our object is made immutable.
Here, in this article, I try to explain JavaScript Objects are Mutable with Examples and I hope you enjoy this JavaScript Objects are Mutable with Examples article.