成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我應該使用 Object 還是 Map?

開發(fā) 前端
本文將會探討一下 Object 和 Map 的不同,從多個角度對比一下 Object 和 Map,希望讀完本文的你可以在日后的項目中做出更為合適的選擇。

 前言

在日常的 JavaScript 項目中,我們最常用到的數(shù)據(jù)結構就是各種形式的鍵值對格式了(key-value pair)。在 JavaScript 中,除了最基礎的 Object 是該格式外,ES6 新增的 Map 也同樣是鍵值對格式。它們的用法在很多時候都十分接近。不知道有沒有人和我一樣糾結過該選擇哪個去使用呢?在本菜最近的項目中,我又遇到了這樣的煩惱,索性一不做二不休,去對比一下究竟該使用哪一個。

本文將會探討一下 Object 和 Map 的不同,從多個角度對比一下 Object 和 Map:

用法的區(qū)別:在某些情況下的用法會截然不同

句法的區(qū)別:創(chuàng)建以及增刪查改的句法區(qū)別

性能的區(qū)別:速度和內存占用情況

希望讀完本文的你可以在日后的項目中做出更為合適的選擇。

用法對比

對于 Object 而言,它鍵(key)的類型只能是字符串,數(shù)字或者 Symbol;而對于 Map 而言,它可以是任何類型。(包括 Date,Map,或者自定義對象)

Map 中的元素會保持其插入時的順序;而 Object 則不會完全保持插入時的順序,而是根據(jù)如下規(guī)則進行排序:

  •   非負整數(shù)會最先被列出,排序是從小到大的數(shù)字順序
  •   然后所有字符串,負整數(shù),浮點數(shù)會被列出,順序是根據(jù)插入的順序
  •   最后才會列出 Symbol,Symbol 也是根據(jù)插入的順序進行排序的

讀取 Map 的長度很簡單,只需要調用其 .size() 方法即可;而讀取 Object 的長度則需要額外的計算:Object.keys(obj).length

Map 是可迭代對象,所以其中的鍵值對是可以通過 for of 循環(huán)或 .foreach() 方法來迭代的;而普通的對象鍵值對則默認是不可迭代的,只能通過 for in 循環(huán)來訪問(或者使用 Object.keys(o)、Object.values(o)、Object.entries(o) 來取得表示鍵或值的數(shù)字)迭代時的順序就是上面提到的順序。 

  1. const o = {};  
  2. const m = new Map();  
  3. o[Symbol.iterator] !== undefined; // false  
  4. m[Symbol.iterator] !== undefined; // true 

在 Map 中新增鍵時,不會覆蓋其原型上的鍵;而在 Object 中新增鍵時,則有可能覆蓋其原型上的鍵: 

  1. Object.prototype.x = 1 
  2.   const o = {x:2};  
  3.   const m = new Map([[x,2]]);  
  4.   o.x; // 2,x = 1 被覆蓋了  
  5.   m.x; // 1,x = 1 不會被覆蓋 

JSON 默認支持 Object 而不支持 Map。若想要通過 JSON 傳輸 Map 則需要使用到 .toJSON() 方法,然后在 JSON.parse() 中傳入復原函數(shù)來將其復原。

對于 JSON 這里就不具體展開了,有興趣的朋友可以看一下這:JSON 的序列化和解析 

  1. const o = {x:1};  
  2.   const m = new Map([['x', 1]]);  
  3.   const o2 = JSON.parse(JSON.stringify(o)); // {x:1}  
  4.   const m2 = JSON.parse(JSON.stringify(m)) // {} 

句法對比

創(chuàng)建時的區(qū)別

Obejct 

  1. const o = {}; // 對象字面量  
  2. const o = new Object(); // 調用構造函數(shù)  
  3. const o = Object.create(null); // 調用靜態(tài)方法 Object.create  

對于 Object 來說,我們在 95%+ 的情況下都會選擇對象字面量,它不僅寫起來最簡單,而且相較于下面的函數(shù)調用,在性能方面會更為高效。對于構建函數(shù),可能唯一使用到的情況就是顯式的封裝一個基本類型;而 Object.create 可以為對象設定原型。

Map 

  1. const m = new Map(); // 調用構造函數(shù)  
  2. 和 Object 不同,Map 沒有那么多花里胡哨的創(chuàng)建方法,通常只會使用其構造函數(shù)來創(chuàng)建。 

除了上述方法之外,我們也可以通過 Function.prototype.apply()、Function.prototype.call()、reflect.apply()、Reflect.construct() 方法來調用 Object 和 Map 的構造函數(shù)或者  Object.create() 方法,這里就不展開了。

新增/讀取/刪除元素時的區(qū)別

Obejct 

  1. const o = {};  
  2. //新增/修改  
  3. o.x = 1 
  4. o['y'] = 2;  
  5. //讀取  
  6. o.x; // 1  
  7. o['y']; // 2  
  8. //或者使用 ES2020 新增的條件屬性訪問表達式來讀取  
  9. o?.x; // 1  
  10. o?.['y']; // 2  
  11. //刪除  
  12. delete o.b; 

對于新增元素,看似使用第一種方法更為簡單,不過它也有些許限制:

屬性名不能包含空格和標點符號

屬性名不能以數(shù)字開頭

對于條件屬性訪問表達式的更多內容可以看一下這:條件屬性訪問表達式

Map 

  1. const m = new Map();  
  2. //新增/修改  
  3. m.set('x', 1);  
  4. //讀取  
  5. map.get('x');  
  6. //刪除  
  7. map.delete('b'); 

對于簡單的增刪查改來說,Map 上的方法使用起來也是十分便捷的;不過在進行聯(lián)動操作時,Map 中的用法則會略顯臃腫: 

  1. const m = new Map([['x',1]]);  
  2. // 若想要將 x 的值在原有基礎上加一,我們需要這么做:  
  3. m.set('x', m.get('x') + 1);  
  4. m.get('x'); // 2  
  5. const o = {x: 1};  
  6. // 在對象上修改則會簡單許多:  
  7. o.x++;  
  8. o.x // 2 

性能對比

接下來我們來討論一下 Object 和 Map 的性能。不知道各位有沒有聽說過 Map 的性能優(yōu)于 Object 的說法,我反正是見過不少次,甚至在 JS 高程四中也提到了 Map 對比 Object 時性能的優(yōu)勢;不過對于性能的概括都十分的籠統(tǒng),所以我打算做一些測試來對比一下它們的區(qū)別。

測試方法

在這里我進行的對于性能測試的都是基于 v8 引擎的。速度會通過 JS 標準庫自帶的 performance.now() 函數(shù)來判斷,內存使用情況會通過 Chrome devtool 中的 memory 來查看。

對于速度測試,因為單一的操作速度太快了,很多時候 performance.now() 會返回 0。所以我進行了 10000 次的循環(huán)然后判斷時間差。因為循環(huán)本身也會占據(jù)一部分時間,所以以下的測試只能作為一個大致的參考。

創(chuàng)建時的性能

測試用的代碼如下: 

  1. let n,  n2 = 5 
  2. // 速度  
  3. while (n2--) {  
  4.   let p1 = performance.now();  
  5.   n = 10000 
  6.   while (n--) { let o = {}; }  
  7.   let p2 = performance.now();  
  8.   n = 10000 
  9.   while (n--) { let m = new Map(); }  
  10.   let p3 = performance.now();  
  11.   console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`);  
  12.  
  13. // 內存  
  14. class Test {}  
  15. let test = new Test();  
  16. test.o = o;  
  17. test.m = m; 

首先進行對比的是創(chuàng)建 Object 和 Map 時的表現(xiàn)。對于創(chuàng)建的速度表現(xiàn)如下:

我們可以發(fā)現(xiàn)創(chuàng)建 Object 的速度會快于 Map。對于內存使用情況則如下:

我們主要關注其 Retained Size,它表示了為其分配的空間。(即刪除時釋放的內存大小)

通過對比我們可以發(fā)現(xiàn),空的 Object 會比空的 Map 占用更少的內。所以這一輪 Object 贏得一籌。

新增元素時的性能

測試用的代碼如下: 

  1. console.clear();  
  2. let n,  n2 = 5 
  3. let o = {}, m = new Map();  
  4. // 速度  
  5. while (n2--) {  
  6.   let p1 = performance.now();  
  7.   n = 10000 
  8.   while (n--) { o[Math.random()] = Math.random(); }  
  9.   let p2 = performance.now();  
  10.   n = 10000 
  11.   while (n--) { m.set(Math.random(), Math.random()); }  
  12.   let p3 = performance.now();  
  13.   console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`);  
  14.  
  15. // 內存  
  16. class Test {}  
  17. let test = new Test();  
  18. test.o = o;  
  19. test.m = m; 

對于新建元素時的速度表現(xiàn)如下:

我們可以發(fā)現(xiàn)新建元素時,Map 的速度會快于 Object。對于內存使用情況則如下:

通過對比我們可以發(fā)現(xiàn),在擁有一定數(shù)量的元素時, Object 會比 Map 占用多了約 78% 的內存。我也進行了多次的測試,發(fā)現(xiàn)在擁有足夠的元素時,這個百分比是十分穩(wěn)定的。所以說,在需要進行很多新增操作,且需要儲存許多數(shù)據(jù)的時候,使用 Map 會更高效。

讀取元素時的性能

測試用的代碼如下: 

  1. let n;  
  2. let o = {}, m = new Map();  
  3. n = 10000 
  4. while (n--) { o[Math.random()] = Math.random(); }  
  5. n = 10000
  6. while (n--) { m.set(Math.random(), Math.random()); }  
  7. let p1 = performance.now();  
  8. for (key in o) { let k = o[key]; }  
  9. let p2 = performance.now();  
  10. for ([key] of m) { let k = m.get(key); }  
  11. let p3 = performance.now();  
  12. `Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms` 

對于讀取元素時的速度表現(xiàn)如下:

通過對比,我們可以發(fā)現(xiàn) Object 略占優(yōu)勢,但總體差別不大。

刪除元素時的性能

不知道大家是否聽說過 delete 操作符性能低下,甚至有很多時候為了性能,會寧可將值設置為 undefined 而不使用 delete 操作符的說法。但其實在 v8 近來的優(yōu)化下,它的效率已經(jīng)提升許多了。

測試用的代碼如下: 

  1. let n;  
  2. let o = {}, m = new Map();  
  3. n = 10000 
  4. while (n--) { o[Math.random()] = Math.random(); }  
  5. n = 10000 
  6. while (n--) { m.set(Math.random(), Math.random()); }  
  7. let p1 = performance.now();  
  8. for (key in o) { delete o[key]; }  
  9. let p2 = performance.now();  
  10. for ([key] of m) { m.delete(key); }  
  11. let p3 = performance.now();  
  12. `Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms` 

對于刪除元素時的速度表現(xiàn)如下:

我們可以發(fā)現(xiàn)在進行刪除操作時,Map 的速度會略占優(yōu),但整體差別其實并不大。

特殊情況

其實除了最基本的情況之外,還有一種特殊的情況。還記得我們在前面提到的 Object 中鍵的排序嗎?我們提到了其中的非負整數(shù)會被最先列出。其實對于非負整數(shù)作為鍵的值和其余類型作為鍵的值來說,v8 是會對它們進行區(qū)別對待的。負整數(shù)作為鍵的部分會被當成數(shù)組對待,即非負整數(shù)具有一定的連續(xù)性時,會被當成快數(shù)組,而過于稀疏時會被當成慢數(shù)組。

對于快數(shù)組,它擁有連續(xù)的內存,所以在進行讀寫時會更快,且占用更少的內存。更多的內容可以看一下這: 探究JS V8引擎下的“數(shù)組”底層實現(xiàn)

在鍵為連續(xù)非負整數(shù)時,性能如下:

我們可以看到 Object 不僅平均速度更快了,其占用的內存也大大減少了。

總結

通過對比我們可以發(fā)現(xiàn),Map 和 Object 各有千秋,對于不同的情況下,我們應當作出不同的選擇。所以我總結了一下我認為使用 Map 和 Object 更為合適的時機。

使用 Map:

儲存的鍵不是字符串/數(shù)字/或者 Symbol 時,選擇 Map,因為 Object 并不支持

儲存大量的數(shù)據(jù)時,選擇 Map,因為它占用的內存更小

需要進行許多新增/刪除元素的操作時,選擇 Map,因為速度更快

 需要保持插入時的順序的話,選擇 Map,因為 Object 會改變排序

需要迭代/遍歷的話,選擇 Map,因為它默認是可迭代對象,迭代更為便捷

使用 Object:

只是簡單的數(shù)據(jù)結構時,選擇 Object,因為它在數(shù)據(jù)少的時候占用內存更少,且新建時更為高效

需要用到 JSON 進行文件傳輸時,選擇 Object,因為 JSON 不默認支持 Map

需要對多個鍵值進行運算時,選擇 Object,因為句法更為簡潔

需要覆蓋原型上的鍵時,選擇 Object

雖然 Map 在很多情況下會比 Object 更為高效,不過 Object 永遠是 JS 中最基本的引用類型,它的作用也不僅僅是為了儲存鍵值對。 

 

責任編輯:龐桂玉 來源: 前端大全
相關推薦

2024-03-18 00:01:00

按鈕鏈接元素

2020-12-29 09:23:14

Windows 10Windows微軟

2021-09-02 07:04:38

JWT簽名算法

2020-07-24 09:20:44

MapObject前端

2018-10-16 09:55:24

Linux發(fā)行版內核

2022-03-15 10:10:41

IT技能人力資源IT領導者

2022-09-08 09:42:26

JavaScripMapObject

2014-12-05 09:49:18

2019-07-05 15:45:39

UbuntuFedoraLinux

2020-08-10 11:20:59

索引MySQL數(shù)據(jù)庫

2015-08-19 10:13:53

DaasVDI

2020-11-03 10:04:53

.proto文件代碼

2015-04-21 09:20:40

SwfitObject—C

2020-03-24 07:40:00

RabbitMQKafka架構師

2023-11-02 08:27:29

2020-12-17 10:17:12

編程開發(fā)計算機

2017-09-19 08:29:51

SSD壽命驅動器

2014-11-13 09:21:23

TCP

2012-06-28 13:37:14

2021-11-02 08:40:42

VS CodeAtom開源
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 拍真实国产伦偷精品 | 久久久久久艹 | 欧美一区二区三区电影 | 午夜寂寞影院列表 | 狠狠综合久久av一区二区小说 | 亚洲高清视频一区二区 | 亚洲日本视频 | 亚洲成a人片| 毛片免费观看 | 99久久精品国产麻豆演员表 | 国产在线a视频 | 国产精品永久在线观看 | 成人免费视频网址 | 一级高清 | 日本又色又爽又黄又高潮 | av网站免费看 | 精品国产99 | 欧美视频中文字幕 | 美女黄色在线观看 | 成人在线观看网站 | www.夜夜骑.com | 在线观看日韩 | 国产亚洲人成a在线v网站 | 久久99精品久久久久 | aaaaaaa片毛片免费观看 | 久久精品av麻豆的观看方式 | 91免费在线 | 午夜影院在线观看免费 | 国产一区二| 美日韩精品 | 色婷婷综合久久久久中文一区二区 | 欧美一级片中文字幕 | 久久se精品一区精品二区 | 久久99精品久久久 | 超碰在线人人 | 日本不卡在线视频 | 亚洲一区二区视频 | 中国一级特黄毛片大片 | 久久er精品 | 久久伊人精品一区二区三区 | 一区二区在线不卡 |