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

How to build your own Angular component library with DevUI

Table of contents Preface Creating a component li...

Things to note when writing self-closing XHTML tags

The img tag in XHTML is so-called self-closing, w...

Example of how to implement underline effects using Css and JS

This article mainly describes two kinds of underl...

Detailed tutorial on building a private Git server on Linux

1. Server setup The remote repository is actually...

Vue implements the method example of tab routing switching component

Preface This article introduces the use of vue-ro...

MySQL Database Indexes and Transactions

Table of contents 1. Index 1.1 Concept 1.2 Functi...

Detailed steps for Python script self-start and scheduled start under Linux

1. Python automatically runs at startup Suppose t...

A brief discussion on the principle of js QR code scanning login

Table of contents The essence of QR code login Un...

How to generate Vue user interface by dragging and dropping

Table of contents Preface 1. Technical Principle ...

Ten useful and simple MySQL functions

function 0. Display current time Command: select ...

A brief discussion on the definition and precautions of H tags

Judging from the results, there is no fixed patte...

Tomcat class loader implementation method and example code

Tomcat defines multiple ClassLoaders internally s...

Vue implements a simple magnifying glass effect

This article example shares the specific code of ...