上集说到ES6中set方法,在ES6中除了增加set方法之外,还考虑到一种场景——键值对的存储
,而map
集合就是专门存储多个键值对(key value pair)的数据。
在map出现之前,我们使用的是对象的方式来存储键值对,键是属性名,值是属性值。键值对数据结合的特点就是:键不可重复
。如果用对象来存储键值对在某些场景下不太如意:
- 键名只能是字符串或者符号,这就给它的使用带来很大的限制
- 获取数据的数量不方便,如果想知道对象中存了多少个数据,就必须先拿到所有的键名,然后通过求数组的长度才能知道对象中有多少个属性。
- 键名容易跟原型上的名称冲突。
0、如何创建map
代码语言:javascript复制
new Map();//创建一个没有任何内容的map集合
new Map(iterable);//创建一个具有初始化内容的map,初始内容来自于可迭代对象每一次迭代的结果,
//但是,它要求每一次迭代的结果必须是一个长度为2的数组,数组第一项表示键,数组第二项表示值
例:创建一个没有任何内容的map集合
代码语言:javascript复制const mp = new Map();
console.log(mp);
执行结果:
例:创建一个有初始内容的map集合
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log(mp);
执行结果:
1、如何进行后续操作
「1、size:只读属性,获取当前map中键的数量」
例:size
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log(mp);
console.log("总数:",mp.size);
执行结果:
「2、set(键,值):设置一个键值对,键和值可以是任何类型」这也是跟Object存储
的区别,对象只能是字符串
例:set()
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
mp.set("d",4)
console.log(mp);
执行结果:
注意点
:
- 如果键不存在,则添加一项
- 如果键存在,则修改它的值
- 判断键存不存在的方式与set相同,都为
Object.is()
例:请问下面map中有几个值?
代码语言:javascript复制 const mp = new Map([["a",1],["b",2],["c",3]]);
mp.set({},4);
mp.set("a",abc);
map.set({},00);
console.log(mp);
console.log("总数:",mp.size);
执行结果:
从结果看:有5个值,对象是引用值,它们的地址不同,所以不会覆盖,而a的原值1会被abc覆盖掉。如果说需要使用相同引用值对象,可以这样改:
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
const obj = {};
mp.set(obj,4);
mp.set("a","abc");
mp.set(obj,00);
console.log(mp);
console.log("总数:",mp.size);
执行结果:
「3、get(键):根据一个键,得到一个值」
例:get(键)
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log("get('a')",mp.get("a"));
执行结果:
例:如果传入不存在的键
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log("get('a')",mp.get("jasnbdjka"));
执行结果:
「4、has(键):判断某个键是否存在」
例:has()
代码语言:javascript复制 const mp = new Map([["a",1],["b",2],["c",3]]);
console.log("has('a')",mp.has("a"));
执行结果:
「5、delete(键):删除指定的键,成功返回true
,失败返回false
」
例:delete(键)
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log("delete('a')",mp.delete("a"));
执行结果:
「6、clear():清空map」
例:clear()
代码语言:javascript复制const mp = new Map([["a",1],["b",2],["c",3]]);
console.log(mp);
2、如何与数组进行转换
例:数组转换成map集合
代码语言:javascript复制//直接把数组放到 new Map(数组)就可以了
const mp = new Map(要转换的数组);
//如下:
const mp = new Map([["a",1],["b",2],["c",3]]);
例:map转换为数组
代码语言:javascript复制//map本身也是一个可迭代的对象,每次迭代的结果就是每一项的值
const mp = new Map([["a",1],["b",2],["c",3]]);
const arr = [...mp];
console.log(arr);
执行结果:
3、遍历
- 使用
for of
循环,每次迭代得到的是一个长度为2的数组
例:for of
const mp = new Map([["a",1],["b",2],["c",3]]);
for (const item of mp) {
console.log(item);
}
执行结果:
当然也可以直接解构
代码语言:javascript复制 const mp = new Map([["a",1],["b",2],["c",3]]);
//方式一:
for (const [key,value] of mp) {
console.log(key,value);
}
//方式二:
for (const item of mp) {
console.log(item[0],item[1]);
}
执行结果:
- 使用
forEach
遍历
- 参数1:每一项的值
- 参数2:每一项的键
- 参数3:map本身
例:forEach
const mp = new Map([["a",1],["b",2],["c",3]]);
mp.forEach((value,key,that) =>{
console.log(value,key,that);
})
执行结果:
4、手写map
手写map方法跟浏览器提供的map方法是不一样的,因为我们没有办法调用底层代码,就当拓展思维了。
1、新建 myMap.js文件
代码语言:javascript复制class MyMap {
constructor(iterable = []) {
//验证是否是可迭代的对象
this.isIterator(iterable);
this._datas = [];
for (const item of iterable) {
//item 也得是一个可迭代对象
this.isIterator(item);
//取出第一个迭代值和第二个迭代值
const iterator = item[Symbol.iterator]();
const key = iterator.next().value;
const value = iterator.next().value;
this.set(key, value);
}
}
//判断是否是可迭代对象
isIterator(target) {
if (typeof target[Symbol.iterator] !== "function") {
throw new TypeError(`${typeof target} ${target} is not is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
}
//set方法
set(key, value) {
const obj = this._getObj(key);
if (obj) {
//如果存在键名,则修改值
obj.value = value;
} else {
this._datas.push({
key,
value
})
}
}
//delete
delete(key) {
for (let i = 0; i < this._datas.length; i ) {
const element = this._datas[i];
if (this.isEqual(element.key, key)) {
this._datas.splice(i, 1);
return true;
}
}
return false;
}
//get方法
get(key) {
const item = this._getObj(key);
if (item) {
return item.value;
}
return undefined;
}
//size方法
get size() {
return this._datas.length;
}
//has方法
has(key) {
return this._getObj(key) !== undefined; //不等于undefined,说明值找到了
}
//clear方法
clear() {
this._datas.length = 0;
}
//forEach
forEach(callback) {
for (const item of this._datas) {
callback(item.value, item.key, this);
}
}
/**
* 根据key值从内部数组中,找到对应的数组项
* @param {*} key
*/
_getObj(key) {
for (const item of this._datas) {
if (this.isEqual(item.key, key)) {
return item;
}
}
}
//使MyMap本身可迭代
*[Symbol.iterator]() {
for (const item of this._datas) {
yield [item.key, item.value]
}
}
/**
* 判断两个数据是否相等
* @param {*} data1
* @param {*} data2
*/
isEqual(data1, data2) {
//如果data1和data2都等于0,那么我们认为它们相等
if (data1 === 0 && data2 === 0) {
return true;
}
return Object.is(data1, data2);
}
代码测试:
代码语言:javascript复制<script src="./js/myMap.js"></script>
<script>
const mp = new MyMap([["a",1],["b",2],["c",3]]);
console.log(mp);
</script>
例:set方法
例:forEach
代码语言:javascript复制<script src="./js/yMap.js"></script>
<script>
const mp = new MyMap([["a",1],["b",2],["c",3]]);
mp.forEach((value,key,that) => {
console.log(value,key,that);
});
</script>
执行结果:
END