ES6中Map数据结构学习笔记

时间:2021-09-12 22:58:08

很多东西就是要细细的品读然后做点读书笔记,心理才会踏实…

Javascript对象本质上就是键值对的集合(Hash结构),但是键只能是字符串,这有一定的限制。

1
2
3
4
var d = {}
var ele = document.body
d[ele] = 'This is body'
console.log(d['[object HTMLBodyElement]'])

ES6中Map数据结构学习笔记

上段代码的原意是将DOM节点作为对象d的键,由于对象只接受字符串,所以ele被自动转为[object HTMLBodyElement]

为了解决这种限制,ES6提供了Map数据结构,类似于对象,但是键的范围不限制于字符串,各类数据类型(包括对象)都可以作为键。

Map基本用法

请看代码

1
2
3
4
5
6
7
8
9
var m = new Map()
m.set('hello', 'Hello guys').set(true, 'right').set({a: 1}, {a: 1}) m.size m.get('hello')
m.has(true)
m.delete(true)
m.has(true)

演示过程如下

ES6中Map数据结构学习笔记

Map构造函数可以接收数组作为参数,该数组的成员是一个个表示键值对的数组,如

1
2
3
4
var arr = [ ['name', 'liujiangbei'], ['title', '屌丝男'] ]

var map = new Map(arr)
console.log(map) // Map { 'name' => 'liujiangbei', 'title' => '屌丝男' }

该过程就好比

1
2
3
var map = new Map()
var arr = [ ['name', 'liujiangbei'], ['title', '屌丝男'] ]
arr.forEach(([key, value]) => map.set(key, value))

另外需要特别注意,只有对同一个对象的引用,Map结构才将其视为同一个key。一定是内存地址是一样的两个值。

ES6中Map数据结构学习笔记

对同一个key进行set,后面的值会覆盖前边的值。

1
2
3
4
5
var m = new Map()
m.set('123', '123')
m.set('123', '3456')
m.get('123')
// 返回 3456

Map的键实际上跟内存地址绑定,只要内存不一样,就视为两个key,这就解决了同名属性碰撞的问题,

如果Map的键是简单类型(数字、字符串、布尔),则只要两个值严格相等,Map就将其视为同一个Key,虽然NaN === NaN为FALSE,但Map将其视为同一Key

1
2
3
4
5
6
let map = new Map()
map.set(NaN, 123)
map.get(NaN) // 123 map.set(-0, 'Zero')
map.get(+0) // Zero

这个地方也要特别注意…

Map实例属性和方法

属性和方法

  1. size属性
  2. set(k, v)
  3. get(k)
  4. has(k)
  5. delete(k)
  6. clear()

遍历方法

  1. keys()
  2. values()
  3. entries()
  4. forEach()
1
for (let [k, v] of map.entries) { console.log(k, v) }

等同于

1
for (let [k, v] of map) { console.log(k, v) }

因为表示Map结构的默认遍历器结构(Symbol.iterator)就是entries方法

1
2
var map = new Map()
console.log(map[Symbol.iterator] === map.entries)

forEach()方法

1
2
3
4
5
var obj = {}
map.forEach(function (key, value, map) {
// do somethings
// this 指向 obj 对象
}, obj)

Map和Array等数据结构的化学反应

Map和Array

前边讲到Map的构造函数接收数组,所以Map和Array之间的转化比较方便,但是也有一些约束。

大专栏  ES6中Map数据结构学习笔记ap">Array转Map

1
2
3
var arr = [[1, 'ext', '1'], ['2', 2], [3, '3', 'ext']]
var map = new Map(arr)
console.log(map)

ES6中Map数据结构学习笔记

ES6中Map数据结构学习笔记

ES6中Map数据结构学习笔记

可以看出数组转为Map需要满足,数组的元素为数组或者object。

Map转Array

利用扩展运算符...很容易实现

1
2
3
4
5
6
7
8
9
10
11
var arr = [
['1', '111'],
[2, [122, 122]],
['name', 'liujiangbei']
]
var map = new Map(arr) var keys = [...map.keys()]
var values = [...map.values()]
var entries = [...map.entries()]
entries === [...map] // false

ES6中Map数据结构学习笔记
ES6中Map数据结构学习笔记

利用Array的map和filter方法实现Map的map和filter特性

Map本身并没有map和filter方法,由于数组和Map转换很方便所以利用数组的map的filter特性从而实现达到map和filter的特性。

1
2
3
4
5
var arr = [[1, '1'], [2, '222'], [3, '333']]
var map = new Map(arr) new Map([...map].filter(([k, v]) => k >= 1))
new Map([...map].map( ([k, v]) => [k * 2, `Map_${v}`] ))

ES6中Map数据结构学习笔记
ES6中Map数据结构学习笔记

Map和Object

Map转为Object

如果Map的键全为字符串、数字、bool,则其可以转为对象,键非字符串的会通过.toString()方法转化。

1
2
3
4
5
6
7
8
9
10
11
12
function mapToObj (map) {
var obj = Object.create(null)
for (let [k, v] of map) {
obj[k] = v
}
return obj
} var map = new Map( [[1, '1'], [true, true], ['111', '111'], [{1: 1}, 111] ])
var obj = mapToObj(map)
console.log(obj)
console.log(typeof obj.true, obj.true)

ES6中Map数据结构学习笔记

Object转为Map

1
2
3
4
5
6
7
8
9
function objToMap (obj) {
let map = new Map()
for (let k of Object.keys(obj)) {
map.set(k, obj[k])
}
return map
} objToMap({yes: true, no: false, 1: 11})

ES6中Map数据结构学习笔记

Map和JSON

Map转为JSON

Map的键都是字符串,这是直接转为对象JSON

1
JSON.stringify(mapToObj(obj))

Map的键有非字符串,这是可选择转为数组JSON

1
JSON.stringify([...map])

JSON转Map

JSON都是字符串的方式,所以先通过JSON.parse(jsonStr)转为对象,然后通过上边的objToMap即可实现转化

有一种特殊情况,整个JSON就是一个数组,诶个数组成员又都是有两个成员的数组,他可以一一对应转为Map

1
new Map(JSON.parse(jsonStr))

结束语

网络上这么多同类型的文章为何我还要多此一举?
看到的永远是别人的,写下来才是自己的,知易行难,日拱一卒,坚持比什么都重要!这句话送给大家也送给我自己…