We All Treat Object as Map in Javascript, No Alternative ?
By: Rezaul Karim
Tags: Data Structure Algorithm, Programming, JavaScript, Objects, Maps

In different languages including javascript , “map” is introduced as a higher order function that uses another function in order to transform any structure (like array) to a certain form . But this is not the same case when we talk about a well renowned data structure called “Map”. Map is a non-linear data structure we often have to use in order to fulfill some specific purposes under certain use cases . Many programming languages provide a built in support for using map ,may be in different names. For example , in python this is called “dictionary” that serves as map. Unfortunately Javascript had nothing called “Map” before Ecmascript2015 got released. This absence compelled the developers growing the habit of using “object” as “Map” whenever it was needed. This blog assumes that you already know javascript (and definitely familiar with Object) and have been using object as Map without giving a second thought like many other programmers out there .In most cases, there is no fatal issue in using object as Map and this blog is not written for discouraging you from using so. Rather i would like to show some anomalies around using object as map in certain use cases and how to avoid those either by following some tricks or using the built-in Map class.

Javascript object facilitates the tasks of a programmer in many ways. The most important one is, you don’t have to create a class in order to leverage the power of an object anytime in your program. For example , if you have to send a group of data to the server in a single request, you can simply create an object with relevant properties having those values .It could have been a lengthy task in other programming languages where creating a class is a mandatory thing before using it’s object. For example

let person = { name : "reza", age : 25, occupation : "student" }

We can see that, person is an object having “name”, “age” and “occupation” as properties. We can know the value of each property in just one go.

console.log(person.name) // returns "reza"

console.log(person.age) // returns 25

Using object.property is a common approach in many programming languages to access object’s property. Javascript provides an alternative way to access the properties as if it treats them in “key-value” pairs . For example,

console.log(person[“name”] ) // returns “reza”

With this much flexibility around js object, we usually treat it as “Map” whenever we need to use map like structure. Javascript ,by its nature is a tricky language that if you are not curious enough to see it’s anomalous behavior , it will keep you in peace [but life seems hell when it starts showing the dark side of the moon].We will now use the aforementioned example to show some inconsistencies around using javascript object as Map.

console.log("name" in person) // true console.log("address" in person) // false . person has no such property. console.log("toString" in person) // true . but why?

First two examples worked as expected, but in third one, despite “person” object’s having no key like “toString” , it returned true . This is so weird ,right ?

Let’s try to understand the reason behind this inconsistency ? the “in” operator checks if a given property is valid in an object . Javascript is actually a prototype based language that every object has a thing (object actually) like “prototype” which keeps the record of all ‘its’ inherited properties from the “master/parent” Object/Class. This is how inheritance is ensured in js object via prototype chaining . you can console.dir(“any object”) in your browser’s console to see the prototype chaining .

It is clear that, every object in javascript inherits everything from a “master” Object .For this, we can use a bunch of alien methods for string,arrays without even defining them in our code . “toString” is such a method every object inherits from the master object. Even though “person” object has no key like “toString”, it is defined in it’s master object . I guess, now you have got the point why it returned “true” in last example.

Is there any way to get rid of this inconsistency from our object. The answer is yes . You can simply tell javascript that my object will not have any prototype. if you create your object the following way

Object.create(null)

the created object will have no prototype as well as those “alien” properties and methods in it . Let’s elaborate a bit to understand this.

let person = Object.create(null)

console.dir(person) // it will show no properties in it .

The created object will not inherit anything from the master “Object” unlike the previous one. To check, console.dir it in your browser’s console. Now let’s try to add the properties we want to see in person object.

person.name = "reza"

person.age = 25

console.dir(person) // it will just show name and age as property.

Now if you check anything which is not present in current object, it will show false. Wohooo!

There are other issues in treating object as Map . For example, every property of an object is supposed to be a string. So ,in such use cases where conversion from “key” to “string” is difficult (in case of object and function) , you cannot use object as Map . No worries!! Javascript came up with a new structure called Map (released with Ecmascript 2015) which exactly fulfills our purpose. Why not using this?

let person = new Map()

person.set("name","reza");

person.set("age",25);

person.has("name");// returns true

person.has("age") ; // returns true

person.has("toString") ;// returns false

At first we created the person map. Then, we set two properties for person (name and age) . we then checked the person Map with some keys which gave us the expected result. Remember one thing, if you try to use “in” operator to see anything is valid inside map, you will see some inconsistencies. for example ,

console.log("toString" in person) // still returns true

We will never use “in” operator to check something inside Map. Because , it rather checks things not in the map, but in the object itself. It is obvious that, person itself is an object created in reference of Map class . As a result, “toString” and other keys from prototype will still be valid in person object. but if you check them with “has” method, they will be invalid and return false.

We can also access the value of the properties/keys with “get” method .

person.get("name") // returns "reza"

Here are other advantages of using Map :

It preserves the order of the keys we set while it is not guaranteed in case of object.

We can easily find the size of map with size method while it’s not that straightforward in object.

Last but not the least, Map is not a replacement for using object as map. You can still treat our sweet “object” as map following certain rules. For example, Object.keys(“myobject”) will return only the keys of myobject. Another alternative to using “in” operator is “hasOwnProperty” method, as it will not take inherited properties into consideration while checking .To sum up, I just tried to shed some light on different aspects of Object and Map .Its up to you which one you will use in different use cases. Happy Coding!!

reference : Eloquent Javascript , MDN .