Map
Map是一个键值对的集合,和object类似,Map作为构造函数,可以通过全局对象获取到。需要通过new操作创建实例对象,直接调用会报错。Map构造函数接受一个iterable类型的函数,用来初始化Map。
var m = new Map([
[1, "1"],
["hello", "world"],
]);
console.log(m);
var n = Map();
console.log(n);
和Object的区别
1.object的key只能是字符串类型和symbol类型,Map的key可以是任意javascript类型
2.Map的key是有序的,迭代时按照插入key的顺序,object的key是无序的,es6以后,object的key也有序的了
3.在频繁的增删键值对的情况下,Map的表现更好,object没有做优化
Map对象的属性
size:用来获取Map中的条目数量
Map对象的方法
clear:清空对象中的条目
delete:删除特定的条目
get:获取特定的条目
has:检测是否包含特定的条目
set:设置特定的条目,如果已经包含,就更形该条目
迭代Map对象
entries(): 返回包含[key,value]的迭代器
keys():返回包含key的迭代器
values(): 返回包含value的迭代器
forEach():传入迭代处理函数遍历所有条目
for…of循环:和entires()的函数表现类似,循环内部对迭代器做了处理
注意:
迭代Map对象的过程中,新增的键值对可以被访问到,已经访问过的键值对,删除后再次添加进来的,会被再次访问,删除没有访问过的键值对,将不会被访问到。
set vs Array/Map vs Object性能对比
var m = new Map([
[1, "1"],
["hello", "world"],
]);
console.log(m);
let map = new Map();
// 存储对象,相同键值对可以去重
map.set(1, "1");
map.set(1, "2");
map.set(2, "3");
map.set("x", "6");
console.log(map);
console.log(map.get(1), map.get(2));
map.delete(1);
console.log(map.has(1));
// 遍历
for (let entries of map) {
//entries 是[k,v]数组
console.log(entries);
}
//实际开发中用于Map只存在于js中,不利于数据传输,需要进行转换
let arr = Array.from(map);
console.log(arr);
//转换成对象
let obj = Object.fromEntries(map);
console.log(obj);
// 性能对比
let obj2 = {};
let map2 = new Map();
function each(cb) {
for (let i = 0; i < 1000000; i++) {
cb(i + "_", i);
}
}
console.time("map");
each((key, val) => {
map2.set(key, val);
});
each((key, val) => {
map2.delete(key);
});
console.timeEnd("map");
console.time("obj");
each((key, val) => {
obj2[key] = val;
});
each((key, val) => {
delete obj2[key];
});
console.timeEnd("obj");
// 数组查找快,链表增删快,Map结合数组+链表的优势实现高性能增删改查
Map实现
let count = 8;
function MyMap() {
//构造器
this.initStore();
}
MyMap.prototype.initStore = function () {
this.store = new Array(count); //创建一个长度为8的数组用来存储(8个房间)
for (let i = 0; i < this.store.length; i++) {
this.store[i] = {
next: null,
};
}
};
MyMap.prototype.set = function (k, v) {
// 通过key计算余数8,取得房间号
let roomIndex = this.hash(k);
// 取出链表头
let queue = this.store[roomIndex];
// 找元素
while (queue.next) {
// 不断地向下找
if (queue.next.key === k) {
// 覆盖
queue.next.value = v;
} else {
queue = queue.next;
}
}
//第一次执行到这里就是第一个数据 k:1
//第二次执行到这里就是末尾的一个
queue.next = {
next: null,
key: k,
value: v,
};
};
MyMap.prototype.get = function (k) {
// 通过key计算余数8,取得房间号
let roomIndex = this.hash(k);
// 取出链表头
let queue = this.store[roomIndex];
queue = queue.next;
while (queue) {
if (queue.key === k) {
return queue.value;
} else {
// 指针下移
queue = queue.next;
}
}
return undefined;
};
MyMap.prototype.hash = function (k) {
return k % count;
};
MyMap.prototype.has = function (k) {
return this.get(k) !== undefined;
};
let m = new MyMap();
m.set(1, "a");
m.set(2, "b");
m.set(3, "c");
m.set(4, "d");
m.set(5, "e");
m.set(6, "f");
m.set(7, "g");
m.set(8, "h");
m.set(9, "k");
console.log(m);
console.log(m.get(1), m.get(3), m.get(9));