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 deploy Tencent Cloud Server from scratch

Since this is my first post, if there are any mis...

Introduction to Common XHTML Tags

<br />For some time, I found that many peopl...

Analysis of MySQL's method of exporting to Excel

This article describes how to use MySQL to export...

WeChat applet implements a simple calculator

WeChat applet's simple calculator is for your...

The connection between JavaScript and TypeScript

Table of contents 1. What is JavaScript? 2. What ...

Vue multi-page configuration details

Table of contents 1. The difference between multi...

Organize the common knowledge points of CocosCreator

Table of contents 1. Scene loading 2. Find Node 1...

How to add a paging navigation bar to the page through Element UI

need Add a paging bar, which can jump to the page...

Bootstrap 3.0 study notes grid system case

Preface In the previous article, we mainly learne...

Zen coding for editplus example code description

For example, he enters: XML/HTML Code div#page>...

VMware Workstation 15 Pro Installation Guide (for Beginners)

01. VMware Workstation Pro 15 Download Download: ...

Detailed explanation of basic management of KVM virtualization in CentOS7

1. Install kvm virtualization : : : : : : : : : :...

Implementation code of html floating prompt box function

General form prompts always occupy the form space...

Detailed tutorial on VMware installation of Linux CentOS 7.7 system

How to install Linux CentOS 7.7 system in Vmware,...