Javascript advance object constructor methods and uses: Part 1

Shubham Akodiya
GAMMASTACK
Published in
9 min readFeb 3, 2020

In this article, we’ll dive into some special object constructor methods and their uses. Often times, we encounter some strange behavior of objects but instead of going deeper and solving the riddle, we usually jump to StackOverflow for finding the alternate approach. Using this way, we can easily get the solution by finding the green tick answers :) but we deprive ourselves of the proper understanding of core concepts.

Prerequisites for this article:

  • Object data model
  • Prototype (Must know the difference between object constructor and prototype methods)
  • Closure

Please have a look at the below questions and give time yourself to think about the answer but remember don’t take help of StackOverflow. You can assume a situation like you’re sitting in an exam hall and the guy which is sitting ahead of you is the topper of your class and as usual, he won’t help you with the answers :) So now, you have to focus on your own answer sheet.

  • Why we can’t overwrite the Object.prototype? Even after, we try to assign it to some arbitrary value, it remains the same.

Now, you might think that this prototype object contains all the main methods of Javascript and if it allows us to overwrite the prototype object then the whole application would break and no library will work. Because, in each library, these prototype methods are required to implement the basic functionality.

But if that’s the case then why the same behavior does not occur happen with our custom object.

Please have a look at the below example:

The output of the above code:

Here, as you can see, we can overwrite the prototype object. Now, If you’re owner of a library and you defined some essential methods in the prototype and you don’t want a user to modify these methods (some library allows user to overwrite some prototype methods) then the above thing will ruin your whole library and all your hard work will go in vain.

  • Can we make some object properties readable? For Example, You have defined some properties in the object and you don’t want the user to modify these properties. Such that even after user tries to modify those readable properties, they remain same.
  • Can we modify some object properties to hide them from iterable? Please have a look at the below examples -

Note: In this article, we’re not covering the concept of Iterator.

Example 1:

let obj = {name: ‘Shubham’, address: ‘India’};
console.log(Object.keys(obj));
// Output -> ['name', 'address']

Can we modify the above object in such a way that it would only return one key i.e address? Take the broad picture of this case in the below example.

Example 2:

The output of the above code :

You can clearly notice from the output that how dangerous is the above code because you’re getting the constructor methods in the output of ‘Object.keys()’ and with each iteration, you end up getting some extra keys and you will need to apply some filtering which is not a good approach. Here, we have only one person object i.e ‘obj’ but you can think of how inefficient the above code will be when we have 20 person objects.

You may think that if we shouldn’t use function constructor methods, rather we can add all the constructor methods to prototype. Then, we’ll not get those constructor methods in the ‘Object.keys’ output. That’s good but here you have modified the whole structure, the condition is that you have to define these methods inside the constructor and output of ‘Object.keys()’ method shouldn’t contain these constructor methods.

We have some special Object function constructor methods and you might wonder why these methods are not appearing in the iterator -

  • keys
  • assign
  • defineProperties
  • defineProperty
  • getOwnPropertyDescriptor
  • getOwnPropertyDescriptors

Lists of more methods like this:

So here, we have a total of three questions to answer. Please take your time.

Timeout!! Now, Answer time.

Before the answer, we need to understand some Object constructor methods -

  • Object.defineProperty
  • Object.defineProperties
  • Object.getOwnPropertyDescriptor
  • Object.getOwnPropertyDescriptors

Object.getOwnPropertyDescriptors:

This method is used to get all property descriptors of an object. For the property descriptors, please have a look at the below example -

Object.defineProperty:

This method is used for adding the special behavior to object property with value. You can check the MDN link further. This method has some property descriptors -

  • Configurable: It is used to modify the property descriptor.
  • Enumerable: It is used to disallow the property from the iterator.
  • Value: Value can be anything. The default value of this property is Undefined.
  • Writable: This property allows us to modify the content.
  • Get: The method to get the value. The default value of this property is Undefined.
  • Set: The method to set the value. The default value of this property is Undefined.

Have you got bored with the theory? Don’t worry, Now we’ll practically take a look of all above mentioned properties.

If we want to add a property to an object. Then we usually use below syntax -

let obj = { ‘name’: ‘shubham’ };

Now, if we want to fetch the descriptors then we will have to use Object.getOwnPropertyDescriptors and the output would be -

Object.getOwnPropertyDescriptors(obj)
{
name: {
value: "shubham",
writable: true,
configurable: true,
enumerable: true
}
}

Here, we can notice the following -

  • value: Value of the property ‘name’
  • writable: True means, we can mutate the value of property ‘name’.
  • configurable: True means, we can modify the descriptor.
  • enumerable: True means, allow to iterate.

Now, back to the questions -

Can we make the property ‘name’ readable of the above object?

Yes, Using the defineProperty method. Please have a look at the below example.

Can we disallow the property ‘name’ from the iterator?

Yes using the same method.

But we need to notice one thing here is that, even if we have changed the enumerable and writable property descriptors but still user can use the same method Object.defineProperty to modify the descriptors again. For example, If user want to make the ‘name’ property writable again then he can do Object.defineProperty(obj, ‘name’, {writable: true});

Can we restrict the modification of descriptor property?

Yes, Now comes the configurable property descriptor.

Can we restrict the prototype object modification? (Not allowing user to overwrite/reassign the prototype object, same as Object.prototype)

Before answering this question, let’s dive into the Object properties to check the descriptors of each property including the ‘prototype’ (after all ‘prototype’ is also a property of an object)

As you can see, writable is set to false for the prototype property of an Object. Thus, despite modification, Object.prototype still remains the same. So if we need to disallow the object prototype reassign/modification then we need to modify the descriptor of ‘prototype’ property to false. Please have a look at the example -

As you can see above, Despite assigning the Person.prototype to {} it still remains the same.

We can also define the property descriptor at the time of assigning the value using the below syntax.

let obj = {};Object.defineProperty(
obj,
‘name’,
{
value: ‘shubham’,
writable: false,
configurable: false,
enumerable: false
}
)

Object.defineProperties is same as the Object.defineProperty but it is used for add/modify the multiple properties with property descriptors and same for the Object.getOwnPropertyDescriptor.

Please have a look at the below simple example that contains all the concepts which we have gone through so far.

This is a simple example to demonstrate what can be the real use case of object constructor methods. This example is related to the shop where, before purchasing any item, User will have to buy tokens. A token rate is equal to the amount. Suppose, If you have amount 80 (any currency) then you will get 80 tokens. In case of token expired, you can buy some new tokens.

Note: This example may have some logical error but its main purpose is to cover all the concepts practically.

In this example, user can’t modify the object property directly and that’s the power of object constructor methods and that’s why these methods are used by most of the JS libraries. A ‘tokens’ is the read-only property and if a user tries to mutate this property without calling the shoppingToken constructor methods then we’ll give him three chance and if he still tries to modify this property then his account will be blocked. He can’t use any methods of shoppingToken.

Follow this link to run the example: https://codepen.io/shubhamak123/pen/PowgVXQ

Important points to note of given example -

  • Object.keys() returns only three properties because we have set ‘enumerable: false’ for the remaining properties.
Object.keys(tokenObj) => [“customerName”,”id”, “tokens”];
  • We can’t set the tokens property directly i.e ‘tokenObj.tokens = 8888’ because here this.tokens property is readOnly and if you try to modify it, you’ll get an error as we have used set() descriptor.
  • We’re using a set() method to displaying the error messages when user tries to modify the balance and tokens properties. Set() method can also be used if we need to execute logic to validate some fields whenever the user sets the particular field. In this example, set() method is used for validating the unauthorized attempts, If a user tries to modify the tokens property. Initially, a user has 3 attempts but if he still tries to modify the tokens property then his account will be blocked. So, If we only need to disallow the writable operation and don’t require to show any error message to the user and no further validation require to any field then we can use writable: false otherwise we can go with set() method. But we can’t use both at the same time.
  • You can’t modify the constructor methods directly because we used ‘writable: false’.
  • You can’t modify the descriptor of constructor properties because we used ‘configurable: false’ here.
  • Here balance and this.balance both are different in shoppingToken method. We’re exposing ‘this.balance’ which is not writable and inside the method, we’re modifying the balance variable which is inside the local closure scope and thus it is not accessible outside of this method. Same for the variable tokens. I have debugged this method, please have a look at below.
  • showHelpMessage is a prototype method which displays the message to the user when his account is blocked. User can’t overwrite the prototype object of shoppingToken and this method.

You can see uses of these methods in libraries:

  • React:
  • Redux

Hope, you have understood all the answers. Thank you very much for reading this article.

--

--