小手一敲,讓JS Map現原形


一.前言


文章主要講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數組中找到相應的位置,取出成績。這樣的話有兩個缺點:

  1. 數組越長,需要查詢耗時越長。
  2. 如果數據很多,導入數據的時候,很容易出錯。

如果用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拿出,如果需要刪除的keyv.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方法的簡單實現就完成啦,看完文章你可以去試試其他方法的實現~

  • 總結
  1. Map 的鍵可以是任意值,包括函數、對象、基本類型。
  2. Map 中的鍵值是有序的,因此,當對它進行遍歷時,Map 對象是按插入的順序返回鍵值。
  3. Map 可直接進行迭代
  4. Map 在涉及頻繁增刪鍵值對的場景下會有些性能優勢。
  5. 對於小白來說,挑選一個簡單的方法來進行源碼實現,真的是不錯的選擇,可以打破內心的恐懼,如果你也有這種恐懼,快去試試吧。手寫源碼,面試常考,雖然有許多大佬,也發表了相關文章,但是靠背是記不住的,還是要自己寫寫。

結束

恭喜你看完這篇文章啦,如果有錯誤的話就麻煩大家給我指出來吧!覺得不錯的話,來個👍鼓勵一下,哈哈

參考文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章