Map集合的出现以及为什么使用Map?
map集合存储的是键值对,键值对数据集合的特点:键不可重复
在map出现之前,我们使用的是对象的方式来存储键值对,键是属性名,值是属性值。
使用对象存储有以下问题:
-
键名只能是字符串
-
获取数据的数量不方便
-
键名容易跟原型上的名称冲突
如何创建map以及map如何操作
new Map(); //创建一个空的map
new Map(iterable); /iterabal是一个长度为2的数组,数组第一项表示键,数组的第二项表示值
1.如何进行后续操作
size:只读属性,获取当前map中键的数量
set(键, 值):设置一个键值对,键和值可以是任何类型
- 如果键不存在,则添加一项
- 如果键已存在,覆盖原来的值
get(键): 根据一个键得到对应的值
has(键):判断某个键是否存在
delete(键):删除指定的键
clear(): 清空map
2.和数组互相转换: [...map]
3.比较键的方式和set相同(Object.is)
4.遍历
- for-of,每次迭代得到的是一个长度为2的数组
- forEach,通过回调函数遍历
- 参数1:每一项的值
- 参数2:每一项的键
- 参数3:map本身
Map实现
构造器
constructor(iterator = []) {
if (typeof iterator[Symbol.iterator] !== "function") {
throw new TypeError(`你提供的${iterator}不是一个可迭代对象`)
}
this._data = []
for (const item of iterator) {
if (typeof item[Symbol.iterator] !== "function") {
throw new TypeError(`${item}不是一个可迭代对象`)
}
//得到迭代器,调用迭代器拿到每一项的key和value
const iterator = item[Symbol.iterator]()
const key = iterator.next().value
const value = iterator.next().value
this.set(key, value)
}
}
辅助函数
/**
* 根据key从内部的数组中找到对应的数据项
* @param {*} key
*/
_getObj(key) {
for (const item of this._data) {
if (this._isEqual(item.key, key)) {
return item
}
}
}
/**
* 判断两个数据是否相等
* @param {*} data1
* @param {*} data2
*/
_isEqual(data1, data2) {
if (data1 === 0 && data2 === 0) return true
return Object.is(data1, data2)
}
set
set(key, value) {
const obj = this._getObj(key)
if (obj) {
//覆盖
obj.value = value
}
else {
//添加
this._data.push({
key,
value
})
}
}
get
get(key) {
const obj = this._getObj(key)
if (obj) {
return obj.value
}
return undefined
}
has与size(只读属性)
has(key) {
return this._getObj(key) !== undefined
}
get size() {
return this._data.length
}
删除与清除
delete(key) {
for (let index = 0; index < this._data.length; index++) {
let temp = this._data[index]
if (this._isEqual(temp.key, key)) {
this._data.splice(index, 1)
return true
}
}
return false
}
clear() {
this._data.length = 0
}
满足可迭代协议
//需要满足可迭代协议
*[Symbol.iterator]() {
for (const obj of this._data) {
yield [obj.key, obj.value]
}
}
forEach
forEach(callback) {
for (const obj of this._data) {
callback(obj.value, obj.key, this)
}
}