Map特点
1.有属性名、属性值,键值对不重复,若属性相同会被新添加的键值对覆盖
2.属性名数据类型:function、{}、NaN、number、[]、undefined、null、boolean、string
3.原型方法:set()、get()、delete()、clear()、has()
模拟实现
hash算法:利用hash算法将属性值转化为0-8之间的,进而放入桶中
桶:利用数组模拟实现桶存储结构
链表:hash算法转化到特定区间的数据,相同的存储到同一链表上
function Map() {
this.bucketLength = 8;
this.init();
}
Map.prototype.init = function () {
this.bucket = new Array (this.bucketLength);
for (let i = 0; i < this.bucket.length; i ++){
this.bucket[i] = {
type:'bucket' + i,
next:null,
}
}
}
Map.prototype.hash = function (key) {
let hash = 0;
if ( typeof key !== 'string'){
if(typeof key == 'number'){
// number NaN
hash = Object.is(key , NaN) ? 0 : key;
hash %= 8;
}else if(typeof key == 'object'){
//null {} []
hash = 1;
}else if(typeof key == 'boolean'){
//boolean
hash = Number(key);
}else{
//undefined function
hash = 2;
}
}else{
//string 转化规则:字符串前三位assic码相加求余
for (let i = 0; i < 3; i++){
hash += key[i] ? key[i].charCodeAt(0) : 0;
}
hash %= 8;
}
return hash;
}
Map.prototype.set = function (key,value) {
let hash = this.hash(key);
let tempBucket = this.bucket[hash];
while(tempBucket.next){//!= null
if(tempBucket.next.key == key){
tempBucket.next.value = value;
return false;
}else{
tempBucket = tempBucket.next;
}
}
tempBucket.next = {
key:key,
value:value,
next:null
}
return true;
}
Map.prototype.get = function (key){
let hash = this.hash(key);
let tempBucket = this.bucket[hash];
while(tempBucket){
if(tempBucket.key == key){
return tempBucket.value;
}else{
tempBucket = tempBucket.next;
}
}
return undefined;
}
Map.prototype.delete = function (key) {
let hash = this.hash(key);
let tempBucket = this.bucket[hash];
while(tempBucket.next){
if(tempBucket.next.key == key){
tempBucket.next = tempBucket.next.next;
return true;
}else{
tempBucket = tempBucket.next;
}
}
return false;
}
Map.prototype.has = function (key) {
let hash = this.hash(key);
let tempBucket = this.bucket[hash];
while (tempBucket){
if(tempBucket.key && tempBucket.key == key){
return true;
}else{
tempBucket = tempBucket.next;
}
}
return false;
}
Map.prototype.clear = function () {
this.init();
}
let oMap = new Map();
oMap.set('name','19');
oMap.get('name');//19