Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

We all know that maps are used to store key-value pairs, and objects in JavaScript are made up of key-value pairs, so what’s the point of having a Map?

Don’t treat objects like maps

1. It is possible to access undefined attributes through the stereotype chain

Assuming the existing scenario, to develop a website that needs to provide Japanese, Chinese and Korean languages, we can define a dictionary to manage.

const dictionary = {
    'ja': {
        'Ninjas for hire': The verbal abuse of ninja employ UN,},'zh': {
        'Ninjas for hire': Ninja For Hire,},'ko': {
        'Ninjas for hire': '용 닌자',}}console.log(dictionary.ja['Ninjas for hire']) The ninja を hired alun
console.log(dictionary.zh['Ninjas for hire']) // Ninja for rent
console.log(dictionary.ko['Ninjas for hire']) // 용 닌자
Copy the code

So we can manage dictionaries in different languages. However, problems arise when we try to access constroctor properties.

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

We expect undefined for a nonexistent property, but instead access the undefined property via the stereotype chain, the constructor property of the stereotype object, pointing to the constructor.

One solution here is to set the stereotype to NULL

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

2. The Key of an object can only be a string

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


      
*/
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 Copy the code

The data for the first element is overwritten because the key in the object can only be a string, which implicitly calls toString() for conversion when we don’t use a string. Both HTML elements are then converted to object HTMLDivElement.

Using the Map

1. Common Map operations

A 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(a)// Create the Map and initialize it
const map1 = new Map([['key1'.'val1'],
    ['key2'.'val2']])// Set the key-value mapping
map.set(zhangsan, {
    region: 'HB'
})
map.set(xiaoming, {
    region: 'HN'
})
// Get the corresponding value based on key
console.log(map.get(zhangsan)) // { region: 'HB' }
console.log(map.get(xiaoming)) // { region: 'HN' }
// Get the nonexistent key and get undefined
console.log(map.get(lihua))     // undefined
// Check whether the specified key exists by using the has function
console.log(map.has(lihua))     // false
console.log(map.has(xiaoming))  // true
// map Stores the number of mappings
console.log(map.size)           / / 2
// delete Deletes the 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
Copy the code

2. Traverse the Map

Map ensures that the order of traversal is the same as the order of insertion

const zhangsan = { name: 'zhangsan' }
const xiaoming = { name: 'xiaoming' }
const map = new Map()
map.set(zhangsan, { region: 'HB' })
map.set(xiaoming, { region: 'HN' })

for (let item of map) { // = for (let item of map.entries()) {
    console.log(item)
}
// Each key-value pair returns an array of [key, value]
// [ { name: 'zhangsan' }, { region: 'HB' } ]
// [ { name: 'xiaoming' }, { region: 'HN' } ]
for (let key of map.keys()) {
    console.log(key)
}
/ / traverse the key
// { name: 'zhangsan' }
// { name: 'xiaoming' }
for (let key of map.values()) {
    console.log(key)
}
/ / traverse the value
// { region: 'HB' }
// { region: 'HN' }
Copy the code

3. Check whether keys are equal in the Map

Map uses the SameValueZero comparison operation internally.

About SameValue and SameValueZero

SameValue (object.is ()) is treated differently for NaN and +0, -0 compared to strict equality (===)

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

SameValueZero differs from SameValue mainly in 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
Copy the code

Performance difference between Map and Object

  1. Memory footprint

This varies by browser, but given a fixed size of memory, Map can store approximately 50% more key/value pairs than Object.

  1. Insert performance

Map is relatively fast. If a large number of operations are required, you are advised to use Map.

  1. To find the 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 optimizes when Object is used as an array. If a lot of lookups are involved, Object is a better choice.

  1. Delete the performance

If your code involves a lot of deletions, Map is recommended.

The resources

  • JavaScript Ninja Secrets (2nd Edition)
  • JavaScript Advanced Programming (4th Edition)