Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 7, 2021 04:57 am GMT

Why to use Maps over Objects in JS ?

In JavaScript, an object is a standalone entity, with properties and type.

Compare it with a cup, for example. A cup is an object, with properties. A cup has color, design, weight, and the material it is made of, etc.

Enough talk

Table Of Contents

1. Problems I faced while working with objects:

  • Only string or symbol could be used as key.

    • Objects have a limitation that their keys have to be strings
       const names = {     1: 'One',     2: 'Two',   };   Object.keys(names); // => ['1', '2']
    • The numbers 1 and 2 are keys in the names object. Later, when the objects keys are accessed, it turns out that the numbers were converted to strings.
    • Implicit conversion of keys is tricky because you lose the consistency of the types.
  • No proper helper methods to work with objects.

    • In order to find the length of the object we need to either use Object.keys() or Object.values() and then find the length by accessing .length on the array returned.
    • Similarly to iterate over it we have to use the same methods above to perform an iteration over the object.
  • Own object properties might collide with property keys inherited from the prototype (e.g. toString, constructor, etc).

    • Any object inherits properties from its prototype object.
    • The accidentally overwritten property inherited from the prototype is dangerous. Lets study such a dangerous situation.
    • Lets overwrite the toString() property in an object actor:
       const actor = {    name: 'Harrison Ford',    toString: 'Actor: Harrison Ford'    /*    this will cause a problem since we are overriding the    toString method of the prototype chain   */  };
  • Deleting keys causes problem in large objects.

    • Using delete causes various forms and magnitudes of a slowdown in many situations, because it tends to make things more complicated, forcing the engine (any engine) to perform more checks and/or fall off various fast paths.

2. Solution: Using Maps Data Structure

Maps is a collection of keyed data items, just like an object. But the main difference is that Map allows keys of any type.

Methods and properties are:

  • new Map() creates the map.
  • map.set(key, value) stores the value by the key.
  • map.get(key) returns the value by the key, undefined if the key doesnt exist in map.
  • map.has(key) returns true if the key exists, false otherwise.
  • map.delete(key) removes the value by the key.
  • map.clear() removes everything from the map.
  • map.size returns the current element count.

Code:

let map = new Map();map.set('1', 'str1');   // a string keymap.set(1, 'num1');     // a numeric keymap.set(true, 'bool1'); // a boolean key// remember the regular object? it would convert keys to string// Map keeps the type, so these two are different:alert( map.get(1)   ); // 'num1'alert( map.get('1') ); // 'str1'alert( map.size ); // 3

Maps have useful and intuitive helper methods which are used to perform different operations.

3. Comparison: Objects and Maps

ParametersObjectMaps
Accidental KeysAn object has a prototype, so it contains default keys that could collide with your own keys if you're not careful.A Map does not contain any keys by default. It only contains what is explicitly put into it.
Key TypesThe keys of an object must be either a String or a Symbol.A Map's keys can be any value (including functions, objects, or any primitive).
SizeThe number of items in an object must be determined manually.The number of items in a Map is easily retrieved from its size property.
PerformanceNot optimized for frequent additions and removals of key-value pairs.Performs better in scenarios involving frequent additions and removals of key-value pairs.

4. Practical Example

Let's take an example of implementing select all functionality.

Select All

const selectedItems = {}; // we will use object here for quick lookup since its search is O(1)// adding item into selectedItemsselectedItems['image/png'] = true selectedItems['text/html'] = true// removing item from selectedItemsselectedItems['application/pdf'] = false 

The code seems simple, but if you notice we are not deleting the key here we are setting it to false.

Screenshot 2021-10-06 at 1.49.49 PM

So in order to change the header selection state either from partial to complete or vice versa.We need to traverse over the object and detect false and true values.

It would have been easy if we could have deleted items from an object and then had checked the length of the object to determine if the current state is partial or complete.

But delete has performance issues in our V8 engine especially when we want to do multiple deletions of keys.

Maps comes to the rescue, map has delete functionality as well as functionality to return size, unlike object where we need to convert to array and then find the length of it. All without causing performance bottleneck.

const selectedItems = new Map()// adding item into selectedItemsselectedItems.set('image/png') selectedItems.set('text/html')// removing item from selectedItemsselectedItems.delete('application/pdf')

One of the solutions was to set selectionItems to {} when we want to remove all the selected items, but that is not a scalable solution in certain situations.

When we do pagination in a table we have scenarios where select-all is performed to items specific to the current page and not on the items of the next or previous page.

In this case, if we set selectedItems = {} it will reset all the values, which is an incorrect solution.

Hence, maps are more scalable solution since it does not face any problem with respect to the deletion of the key.

5. Problems in Maps

  • Maps is not here to replace objects

    • If we are only using string-based keys and need maximum read performance, then objects might be a better choice.
    • This is because Javascript engines compile objects down to C++ classes in the background, and the access path for properties is much faster than a function call for Map().get().
    • Adding or removing a property causes the shape of the class to change and the backing class to be re-compiled, which is why using an object as a dictionary with lots of additions and deletions is very slow, but reads of existing keys without changing the object are very fast.
  • Maps are not serializable

6. Conclusion

In review, while we will still rely heavily on JavaScript objects to do the job of holding structured data, they have some clear limitations

These limitations are solved by maps. Moreover, maps provide benefits like being iterators and allowing easy size look-up.

Objects are not good for information thats continually updated, looped over, altered, or sorted. In those cases, use maps.

In conclusion, use maps with a purpose. Think of maps and objects similar to how let and const are used for our variables.

Enough talk


Original Link: https://dev.to/faisalpathan/why-to-use-map-over-object-in-js-306m

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To