Why do we need Map when we already have Object in JavaScript?

Why do we need Map when we already have Object in JavaScript?

1. Don’t treat objects as Maps

1. Undefined properties may be accessed through the prototype chain

Assuming the current scenario, when developing a website, we need to provide three languages: Japanese, Chinese, and Korean. We can define a dictionary to manage them.

const dictionary = {
    'ja': {
        'Ninjas for hire': 'Ninjas for hire',
    },
    'zh': {
        'Ninjas for hire': 'Ninjas for hire',
    },
    'ko': {
        'Ninjas for hire': '고용닌자',
    }
}

console.log(dictionary.ja['Ninjas for hire']) // ninjas for hireconsole.log(dictionary.zh['Ninjas for hire']) // ninjas for hireconsole.log(dictionary.ko['Ninjas for hire']) // ninjas for hireconsole.log(dictionary.ko['Ninjas for hire']) // ninjas for hire

In this way, we manage dictionaries in different languages. However, problems arise when we try to access constroctor property.

console.log(dictionary.ko['constructor']) // ƒ Object() { [native code] }

For non-existent properties, we expect to get undefined , but we access undefined properties through the prototype chain. constructor property of the prototype object points to the constructor.

One solution here is to set the prototype to null

Object.setPrototypeOf(dictionary.ko, null)
console.log(dictionary.ko['constructor']) // undefined

2. The key of the object can only be a string

Suppose you need to map key of the object to html node. We write the following code:

/* HTML part <div id="firstElement"></div>
<div id="secondElement"></div>
*/

const firstElement = document.getElementById('firstElement')
const secondElement = document.getElementById('secondElement')

const map = {}

map[firstElement] = {
    data: 'firstElement'
}
map[secondElement] = {
    data: 'secondElement'
}

console.log(map[firstElement].data) // secondElement
console.log(map[secondElement].data) // secondElement

The data of the first element is overwritten because the key in the object can only be of string type. When we do not use the string type, it implicitly calls toString () function for conversion. So both html elements are converted to string [object HTMLDivElement] .

Object keys can also be Symbol , but Symbol keys are ignored during for..in traversal, Object.keys() , and serialization with JSON.stringify() .

2. Using Map

1. Common Map Operations

Map can use any JavaScript data type as a key

function People(name) {
    this.name = name
}
const zhangsan = new People('zhangsan')
const xiaoming = new People('xiaoming')
const lihua = new People('lihua')
// Create a Map
const map = new Map()
// Create a Map and initialize it to convert the two-dimensional key-value array into a Map object const map1 = new Map([
    ['key1', 'val1'],
    ['key2', 'val2'],
])
// Convert Map to a two-dimensional array console.log(Array.from(map1)) // [ [ 'key1', 'val1' ], [ 'key2', 'val2' ] ]
// Set the key-value mapping relationship map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// Get the corresponding value according to the key console.log(map.get(zhangsan)) // { region: 'HB' }
console.log(map.get(xiaoming)) // { region: 'HN' }
// Get the non-existent key and get undefined
console.log(map.get(lihua)) // undefined
// Use the has function to determine whether the specified key exists console.log(map.has(lihua)) // false
console.log(map.has(xiaoming)) // true
//map stores the number of mappingsconsole.log(map.size) // 2
// delete delete key
map.delete(xiaoming)
console.log(map.has(xiaoming)) // false
console.log(map.size) // 1
// clear clears the map
map.clear()
console.log(map.size) // 0

2. Traversing the Map

Map can ensure that the traversal order is consistent with the insertion order

const zhangsan = { name: 'zhangsan' }
const xiaoming = { name: 'xiaoming' }
const map = new Map()
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })
// Each key-value pair returns an array of [key, value] for (let item of map) { // = for (let item of map.entries()) {
    console.log(item)
    // [ { name: 'zhangsan' }, { region: 'HB' } ]
    // [ { name: 'xiaoming' }, { region: 'HN' } ]
}
// Traverse the key
for (let key of map.keys()) {
    console.log(key)
    // { name: 'zhangsan' }
    // { name: 'xiaoming' }
}
// Traverse value
for (let key of map.values()) {
    console.log(key)
    // { region: 'HB' }
    // { region: 'HN' }
}
// Iterate over the Map using the forEach() method
map.forEach(function(value, key) {
    console.log(key, value)
    // { name: 'zhangsan' } { region: 'HB' }
    // { name: 'xiaoming' } { region: 'HN' }
})

3. Determine key equality in Map

Map uses SameValueZero comparison operation internally.

About SameValue and SameValueZero

SameValue ( Object.is() ) handles NaN and +0, -0 differently than strict equality (===)

Object.is(NaN, NaN) // true
Object.is(0, -0) // false

The main difference between SameValueZero and SameValue is whether 0 is equal to -0.

map.set(NaN, 0)
map.set(0, 0)
console.log(map.has(NaN)) // true
console.log(map.has(-0)) // true

4. Copy or merge Map

Maps can be copied like arrays

let original = new Map([
    [1, {}]
])
let clone = new Map(original) // Clone Map

console.log(clone.get(1)); // {}
console.log(original === clone) // false
console.log(original.get(1) === clone.get(1)) // true

Merge multiple maps

let first = new Map([
    [1, 'one'],
    [2, 'two'],
    [3, 'three'],
]);
let second = new Map([
    [1, 'uno'],
    [2, 'dos']
]);
// When merging two Map objects, if there are duplicate key values, the latter will overwrite the former.
// The spread operator essentially converts a Map object into an array.
let merged = new Map([...first, ...second]);

console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three

5. Map Serialization

Map cannot be serialized. If you try to get the JSON of Map using JSON.stringify , you will only get "{}".

Since the key of a Map can be of any data type, and JSON only allows strings as keys, it is generally not possible to convert a Map to JSON.

However, you can try to serialize a Map in the following way:

// Initialize Map(1) {"key1" => "val1"}
const originMap = new Map([['key1', 'val1']])
//Serialize "[[\"key1\",\"val1\"]]"
const mapStr = JSON.stringify(Array.from(originMap.entries())) 
// Deserialize Map(1) {"key1" => "val1"}
const cloneMap = new Map(JSON.parse(mapStr))

3. Performance Differences between Map and Object

Memory usage

The situation varies from browser to browser, but given a fixed amount of memory, Map can store about 50% more key/value pairs than Object .

Insert performance

Map is slightly faster and is recommended if a large number Map operations are involved.

Search speed

The performance difference is minimal, but Object can sometimes be faster if it contains only a small number of key/value pairs. The browser will perform optimization when Object is used as an array. If a large number of lookup operations are involved, Object would be a better choice.

Deletion performance

If the code involves a lot of deletion operations, it is recommended to choose Map .

This concludes the article on why we need Map when we already have Object in JavaScript . For more relevant JavaScript Map content, please search previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Why do we need Map when we already have Object in JavaScript?
  • Conversion between JSONObject objects and Map objects in JAVA
  • Analysis of the differences between Object, map, and weakmap in JavaScript
  • Convert JSONObject to HashMap in Java (method + main method call example)
  • Json string and Object, List, Map conversion tool class
  • Example analysis of Json deserialization ObjectMapper (custom implementation of deserialization method)
  • Example of using ObjectMapper class to implement conversion between Json and bean in java
  • Java code to implement the conversion between Map and Object and between Map and Json
  • How to implement Map using Array and Object in JavaScript

<<:  Descending Index in MySQL 8.0

>>:  In-depth understanding of the creation and implementation of servlets in tomcat

Recommend

12 Laws of Web Design for Clean Code [Graphic]

Beautiful code is the foundation of a beautiful we...

Explain MySQL's binlog log and how to use binlog log to recover data

As we all know, binlog logs are very important fo...

Solve the MySQL login 1045 problem under centos

Since the entire application needs to be deployed...

How to implement Vue timer

This article example shares the specific code of ...

Detailed Analysis of Event Bubbling Mechanism in JavaScript

What is bubbling? There are three stages in DOM e...

Detailed explanation and examples of database account password encryption

Detailed explanation and examples of database acc...

Html long text automatically cuts off when it exceeds the tag width

When we display long text, we often need to interc...

3 common errors in reading MySQL Binlog logs

1. mysqlbinlog: [ERROR] unknown variable 'def...

HTML tags list and usage instructions

List of HTML tags mark type Name or meaning effec...

The latest virtual machine VMware 14 installation tutorial

First, I will give you the VMware 14 activation c...

Telnet is moved to busybox-extras in Alpine image

The telnet in the Alpine image has been moved to ...

Case analysis of several MySQL update operations

Table of contents Case Study Update account balan...