Do you really understand ES6 Set, WeakSet, Map and WeakMap?

Posted Jun 15, 20207 min read

When I was learning ES6 before, I saw Set and Map. I don t know what their application scenarios are. I just think that they are often used in arrays to duplicate and store data. Later, I slowly realized that Set is a A data structure called a collection, Map is a data structure called a dictionary.

This article is included in gitthub: github.com/Michael-lzg

Set

Set itself is a constructor used to generate Set data structure. The Set function can accept an array(or other data structure with an iterable interface) as a parameter for initialization. The Set object allows you to store any type of value, whether it is a primitive value or an object reference. It is similar to an array, but the values of the members are unique and there are no duplicate values.

const s = new Set()
[2, 3, 5, 4, 5, 2, 2].forEach((x) => s.add(x))
for(let i of s) {
  console.log(i)
}
//2 3 5 4

Special values in Set

The value stored by the Set object is always unique, so you need to determine whether the two values are equal. There are several special values that require special treatment:

  • +0 and -0 are identical when stored to determine uniqueness, so do not repeat
  • undefined and undefined are identical, so do not repeat
  • NaN and NaN are not equal, but in Set it is considered that NaN and NaN are equal, so there can only be one, no duplication.

Set properties:

  • size:return the number of elements contained in the collection

    const items = new Set([1, 2, 3, 4, 5, 5, 5, 5])
    items.size //5

Set instance method

  • add(value):add a value and return the Set structure itself(can be chained).

  • delete(value):delete a value, and if it is successfully deleted, it returns true, otherwise it returns false.

  • has(value):returns a Boolean value indicating whether the value is a member of Set.

  • clear():clear all members, no return value.

    s.add(1).add(2).add(2)
    //Note 2 was added twice

    s.size //2

    s.has(1) //true
    s.has(2) //true
    s.has(3) //false

    s.delete(2)
    s.has(2) //false

Traversal method

  • keys():return key name traverser.
  • values():return key value traverser.
  • entries():return key-value traversal.
  • forEach():use callback function to traverse each member.

Since the Set structure has no key names, only key values (or key names and key values are the same value), the behavior of the keys method and the values method are exactly the same.

let set = new Set(['red','green','blue'])

for(let item of set.keys()) {
  console.log(item)
}
//red
//green
//blue

for(let item of set.values()) {
  console.log(item)
}
//red
//green
//blue

for(let item of set.entries()) {
  console.log(item)
}
//["red", "red"]
//["green", "green"]
//["blue", "blue"]

Comparison between Array and Set

  • The indexOf method of Array is less efficient than the has method of Set
  • Set does not contain duplicate values (you can use this feature to deduplicate an array)
  • Set deletes a value through the delete method, while Array can only be done through splice. The former is more convenient to use
  • Many new methods of Array map, filter, some, every, etc. are not in Set(but they can be converted to each other to use)

Set Application

  1. The Array.from method can convert the Set structure into an array.

    const items = new Set([1, 2, 3, 4, 5])
    const array = Array.from(items)

  2. Array deduplication

    //Remove duplicate members of the array
    ;[...new Set(array)]

    Array.from(new Set(array))

3.The array's map and filter methods can also be used indirectly in Set

let set = new Set([1, 2, 3])
set = new Set([...set].map((x) => x * 2))
//Return to Set structure:{2, 4, 6}

let set = new Set([1, 2, 3, 4, 5])
set = new Set([...set].filter((x) => x%2 == 0))
//Return to Set structure:{2, 4}
  1. Implement union(Union), intersection(Intersect) and difference

    let a = new Set([1, 2, 3])
    let b = new Set([4, 3, 2])

    //union
    let union = new Set([...a, ...b])
    //Set {1, 2, 3, 4}

    //intersection
    let intersect = new Set([...a].filter((x) => b.has(x)))
    //set {2, 3}

    //Difference
    let difference = new Set([...a].filter((x) => !b.has(x)))
    //Set {1}

weakSet

The WeakSet structure is similar to Set, and is also a collection of unique values.

  • The members are arrays and array-like objects. If you call the add() method and pass in the parameters of non-array and array-like objects, an error will be thrown.

    const b = [1, 2, [1, 2]]
    new WeakSet(b) //Uncaught TypeError:Invalid value used in weak set

  • Members are weak references, can be recycled by the garbage collection mechanism, and can be used to save DOM nodes, which is not easy to cause memory leaks.

  • WeakSet is not iterable, so it cannot be used in for-of loops.

  • WeakSet has no size attribute.

Map

Stored in Map are key-value pairs in the form of key-value, where key and value can be of any type, that is, objects can also be used as key. The emergence of Map is to allow various types of values to be used as keys. Map provides a "value-value" correspondence.

The difference between Map and Object

  1. The Object object has a prototype, which means it has a default key value on the object, unless we use Object.create(null) to create an object without a prototype;
  2. In Object objects, only String and Symbol can be used as key values, but in Map, key values can be of any basic type(String, Number, Boolean, undefined, NaN .), or objects(Map, Set, Object, Function, Symbol, null .);
  3. Through the size property in Map, you can easily get the length of Map. To get the length of Object, you can only calculate it manually

Map Properties

  • size:Returns the number of elements contained in the collection

    const map = new Map()
    map.set('foo', ture)
    map.set('bar', false)
    map.size //2

Map object methods

  • set(key, val):add new elements to Map

  • get(key):Find a specific value by key and return

  • has(key):determine whether there is a value corresponding to Key in the Map object, return true if there is, otherwise return false

  • delete(key):remove the corresponding data from Map by key value

  • clear():delete all elements in this Map

    const m = new Map()
    const o = {p:'Hello World'}

    m.set(o,'content')
    m.get(o) //"content"

    m.has(o) //true
    m.delete(o) //true
    m.has(o) //false

Traversal method

  • keys():return key name traverser

  • values():return key value traverser

  • entries():return key-value traversal

  • forEach():use callback function to traverse each member

    const map = new Map([

    ['a', 1],
    ['b', 2],

    ])

    for(let key of map.keys()) {

    console.log(key)

    }
    //"a"
    //"b"

    for(let value of map.values()) {

    console.log(value)

    }
    //1
    //2

    for(let item of map.entries()) {

    console.log(item)

    }
    //["a", 1]
    //["b", 2]

    //or
    for(let [key, value]of map.entries()) {

    console.log(key, value)

    }
    //"a" 1
    //"b" 2

    //for...of... traversing the map is equivalent to using map.entries()

    for(let [key, value]of map) {

    console.log(key, value)

    }
    //"a" 1
    //"b" 2

Data type conversion

Map to array

let map = new Map()
let arr = [...map]

Array to Map

Map:map = new Map(arr)

Map to object

let obj = {}
for(let [k, v]of map) {
  obj[k]= v
}

Object to Map

for(let k of Object.keys(obj)){
  map.set(k,obj[k])
}

Application of Map

In some Admin projects, we usually display personal information, such as the following information on the page. The traditional method is as follows.

<div class="info-item">
  <span>Name</span>
  <span>{{info.name}}</span>
</div>
<div class="info-item">
  <span>age</span>
  <span>{{info.age}}</span>
</div>
<div class="info-item">
  <span>Gender</span>
  <span>{{info.sex}}</span>
</div>
<div class="info-item">
  <span>Mobile phone number</span>
  <span>{{info.phone}}</span>
</div>
<div class="info-item">
  <span>home address</span>
  <span>{{info.address}}</span>
</div>
<div class="info-item">
  <span>home address</span>
  <span>{{info.duty}}</span>
</div>

js code

mounted() {
  this.info = {
    name:'jack',
    sex:'Male',
    age:'28',
    phone:'13888888888',
    address:'Guangzhou City, Guangdong Province',
    duty:'General Manager'
  }
}

We use Map to transform, save the label and value we need to display to our Map and render to the page, this reduces a lot of html code

<template>
  <div id="app">
    <div class="info-item" v-for="[label, value]in infoMap" :key="value">
      <span>{{label}}</span>
      <span>{{value}}</span>
    </div>
  </div>
</template>

js code

data:() =>({
  info:{},
  infoMap:{}
}),
mounted() {
  this.info = {
    name:'jack',
    sex:'Male',
    age:'28',
    phone:'13888888888',
    address:'Guangzhou City, Guangdong Province',
    duty:'General Manager'
  }
  const mapKeys = ['Name','Gender','Age','Phone','Home Address','Identity']
  const result = new Map()
  let i = 0
  for(const key in this.info) {
    result.set(mapKeys[i], this.info[key])
    i++
  }
  this.infoMap = result
}

WeakMap

The WeakMap structure is similar to the Map structure, and is also used to generate a set of key-value pairs.

  • Only accept objects as key names(except null), do not accept other types of values as key names
  • The key name is a weak reference, the key value can be arbitrary, the object pointed to by the key name can be garbage collected, and the key name is invalid at this time
  • It cannot be traversed, the methods are get, set, has, delete

to sum up

Set

  • Is a data structure called a collection(new in ES6)
  • Members are unique, disordered and not duplicate
  • [value, value], the key value is the same as the key name(or only the key value, no key name)
  • Allow to store any type of unique value, whether it is the original value or an object reference
  • Can be traversed, the methods are:add, delete, has, clear

WeakSet

  • Members are objects
  • Members are weak references, can be recovered by the garbage collection mechanism, can be used to save the DOM node, it is not easy to cause memory leaks
  • It cannot be traversed, the methods are add, delete, has

Map

  • Is a data structure similar to a dictionary, which is essentially a collection of key-value pairs
  • Can be traversed, can be converted with various data formats
  • Operation methods are:set, get, has, delete, clear

WeakMap

  • Only accept objects as key names(except null), do not accept other types of values as key names
  • The key name is a weak reference, the key value can be arbitrary, the object pointed to by the key name can be garbage collected, and the key name is invalid at this time
  • It cannot be traversed, the methods are get, set, has, delete

recommended article

Build a vue-cli4+webpack mobile terminal framework(out of the box)
Build from zero to optimize a scaffold like vue-cli
Package a toast and dialog component and publish to npm
Build a webpack project from scratch
Summary of several webpack packaging optimization methods
Summary of advanced applications of the vue knowledge system
Summary of practical skills of vue knowledge system
Summary of the basic introduction to the vue knowledge system
Summary of common mobile terminal H5 development skills(full of dry goods!)

My public account that I follow is sharing the front-end knowledge from time to time and making progress with you!