一.前言
文章主要講JS Map對象的用法和如何手寫Map,非常適合初步學習了JS的同學,適當的學會手寫JS源碼的技能,對JS理解和麪試都有很大的幫助。大多數人都知道Map方法的使用,但是在網上對Map源碼實現的文章很少,希望通過這篇文章可以幫助到大家對Map方法的理解。
說在前面
Map 對象保存鍵值對,並且能夠記住鍵的原始插入順序。任何值(對象或者原始值) 都可以作爲一個鍵或一個值。本文會先簡單介紹用法,再介紹手寫Map,
想讓Map現原形就快快花幾分鐘時間瀏覽這篇文章吧!
二. Map方法的使用
Map是一組鍵值對的結構,具有極快的查找速度。
舉個例子,假設要根據同學的名字查找對應的成績,如果用Array實現,需要兩個Array:
var names = ['lm', 'dz', 'xxy'];
var scores = [100, 90, 80];
我們需要實現這個要求,就先要遍歷names
數組,找到需要查詢同學名字的位置,然後去scores
數組中找到相應的位置,取出成績。這樣的話有兩個缺點:
- 數組越長,需要查詢耗時越長。
- 如果數據很多,導入數據的時候,很容易出錯。
如果用Map實現,只需要一個“名字”-“成績”的對照表,直接根據名字查找成績,一個鍵(名字)和對應一個值(成績)進行綁定,無論這個表有多大,,也不用擔心出錯。用JavaScript使用Map實現如下:
var m = new Map([['lm', 100], ['dz', 90], ['xxy', 80]]);
m.get('lm'); //100
m.size();//3
m.set('xp', 90); // 添加新的key-value
m.delete('xxy'); // 刪除key 'xxy'
通過Map的get
方法查詢到lm
同學100分,用size
獲取有多少個鍵值對,用set
方法添加xp
的成績,用delete
方法刪除xxy
的成績。
我們需要注意的是一個key只能對應一個value,多次對一個key放入value,後面的值會把前面的值沖掉:
var m = new Map();
m.set('xp', 70);
m.set('xp', 90);
m.get('xp'); // 90
三.手寫Map方法
想要手寫Map方法,首先需要知道的是它ES6標準新增的數據類型,是鍵/值對的集合。這個數據類型,可以使用很多方法來操作它。下面就讓我們,小手一敲,讓它現出原形吧~
-
定義Map方法
寫一個方法首當其衝的當然是要定義它,並且聲明方法裏面的參數。
/**
*
* 描述:js實現的map方法
* @returns {Map}
*/
function Map(){
var struct = function(key, value) {
this.key = key;
this.value = value;
};
}
-
寫set方法
需要添加鍵值對,我們需要注意的是,如果之前就存在這個鍵值對,需要對它的
value
進行覆蓋更新。如果不存在,則直接保存這對鍵值。
// 添加map鍵值對
var set = function(key, value){
//遍歷數組,如果存在,則進行覆蓋
for (var i = 0; i < this.arr.length; i++) {
if ( this.arr[i].key === key ) {
this.arr[i].value = value;
return;
}
};
//之前的數據裏面沒有這個對鍵值,直接對應保存
this.arr[this.arr.length] = new struct(key, value);
};
-
寫get方法
完成
get
方法,需要實現根據key
獲取value
,如果key
存在則獲取對應的value
,否則返回null
,代碼如下:
// 根據key獲取value
var get = function(key) {
for (var i = 0; i < this.arr.length; i++) {
if ( this.arr[i].key === key ) {
return this.arr[i].value;
}
}
return null;
};
- 寫remove方法
Map
方法中可可以通過key
,來完成刪除鍵值對。要刪除鍵值對,作者想到的是,不管存在與否,遍歷所有數組,先把棧頂的v.key
,用pop
拿出,如果需要刪除的key
與v.key
一致,則continue
,否則用unshift(v)
,將其恢復。代碼如下:
// 根據key刪除
var remove = function(key) {
var v;
for (var i = 0; i < this.arr.length; i++) {
v = this.arr.pop();
if ( v.key === key ) {
continue;
}
this.arr.unshift(v);
}
};
- 寫size和isEmpty方法
這個兩個方法的實現都很簡單,相信每個人都會,我就直接上代碼:
// 獲取map鍵值對個數
var size = function() {
return this.arr.length;
};
// 判斷map是否爲空
var isEmpty = function() {
return this.arr.length <= 0;
};
四、驗證與總結
- 驗證
一個方法有沒有寫對,最好的驗證,就是實踐出真知,下面我附上所有代碼吧
function Map(){
var struct = function(key, value) {
this.key = key;
this.value = value;
};
// 添加map鍵值對
var set = function(key, value){
for (var i = 0; i < this.arr.length; i++) {
if ( this.arr[i].key === key ) {
this.arr[i].value = value;
return;
}
};
this.arr[this.arr.length] = new struct(key, value);
};
// 根據key獲取value
var get = function(key) {
for (var i = 0; i < this.arr.length; i++) {
if ( this.arr[i].key === key ) {
return this.arr[i].value;
}
}
return null;
};
// 根據key刪除
var remove = function(key) {
var v;
for (var i = 0; i < this.arr.length; i++) {
v = this.arr.pop();
if ( v.key === key ) {
continue;
}
this.arr.unshift(v);
}
};
// 獲取map鍵值對個數
var size = function() {
return this.arr.length;
};
// 判斷map是否爲空
var isEmpty = function() {
return this.arr.length <= 0;
};
this.arr = new Array();
this.get = get;
this.set = set;
this.remove = remove;
this.size = size;
this.isEmpty = isEmpty;
}
var map=new Map();
map.set("xxyang",100);
map.set("xxyang",90);
map.set("xp","dz");
console.log(map.get('xxyang'));//90
console.log(map.get('xp')); //dz
console.log(map.size());//2
map.remove("xxyang");
console.log(map.size());//1
console.log(map.get("xxyang"));//null
用vscode
運行得到如下結果:
結果無誤,也可以覆蓋。Map
方法的簡單實現就完成啦,看完文章你可以去試試其他方法的實現~
- 總結
- Map 的鍵可以是任意值,包括函數、對象、基本類型。
- Map 中的鍵值是有序的,因此,當對它進行遍歷時,Map 對象是按插入的順序返回鍵值。
- Map 可直接進行迭代
- Map 在涉及頻繁增刪鍵值對的場景下會有些性能優勢。
- 對於小白來說,挑選一個簡單的方法來進行源碼實現,真的是不錯的選擇,可以打破內心的恐懼,如果你也有這種恐懼,快去試試吧。手寫源碼,面試常考,雖然有許多大佬,也發表了相關文章,但是靠背是記不住的,還是要自己寫寫。
結束
恭喜你看完這篇文章啦,如果有錯誤的話就麻煩大家給我指出來吧!覺得不錯的話,來個👍鼓勵一下,哈哈