91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中Object和Map對比實例分析

發布時間:2022-05-17 10:41:15 來源:億速云 閱讀:364 作者:zzz 欄目:大數據

這篇文章主要介紹“JavaScript中Object和Map對比實例分析”,在日常操作中,相信很多人在JavaScript中Object和Map對比實例分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JavaScript中Object和Map對比實例分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

用法對比

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

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

  •   非負整數會最先被列出,排序是從小到大的數字順序

  •   然后所有字符串,負整數,浮點數會被列出,順序是根據插入的順序

  •   最后才會列出 Symbol,Symbol 也是根據插入的順序進行排序的

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

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

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

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

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

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

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

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

句法對比

創建時的區別

Obejct

const o = {}; // 對象字面量  const o = new Object(); // 調用構造函數  const o = Object.create(null); // 調用靜態方法 Object.create

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

Map

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

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

新增/讀取/刪除元素時的區別

Obejct

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

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

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

屬性名不能以數字開頭

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

Map

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

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

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

性能對比

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

測試方法

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

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

創建時的性能

測試用的代碼如下:

let n,  n2 = 5;  // 速度  while (n2--) {    let p1 = performance.now();    n = 10000;    while (n--) { let o = {}; }    let p2 = performance.now();    n = 10000;    while (n--) { let m = new Map(); }    let p3 = performance.now();    console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`);  }  // 內存  class Test {}  let test = new Test();  test.o = o;  test.m = m;

首先進行對比的是創建 Object 和 Map 時的表現。

我們可以發現創建 Object 的速度會快于 Map。

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

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

新增元素時的性能

測試用的代碼如下:

console.clear();  let n,  n2 = 5;  let o = {}, m = new Map();  // 速度  while (n2--) {    let p1 = performance.now();    n = 10000;    while (n--) { o[Math.random()] = Math.random(); }    let p2 = performance.now();    n = 10000;    while (n--) { m.set(Math.random(), Math.random()); }    let p3 = performance.now();    console.log(`Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`);  }  // 內存  class Test {}  let test = new Test();  test.o = o;  test.m = m;

對于新建元素時的速度表現如下:

JavaScript中Object和Map對比實例分析

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

JavaScript中Object和Map對比實例分析

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

讀取元素時的性能

測試用的代碼如下:

let n;  let o = {}, m = new Map();  n = 10000;  while (n--) { o[Math.random()] = Math.random(); }  n = 10000; while (n--) { m.set(Math.random(), Math.random()); }  let p1 = performance.now();  for (key in o) { let k = o[key]; }  let p2 = performance.now();  for ([key] of m) { let k = m.get(key); }  let p3 = performance.now();  `Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`

對于讀取元素時的速度表現如下:

JavaScript中Object和Map對比實例分析

通過對比,我們可以發現 Object 略占優勢,但總體差別不大。

刪除元素時的性能

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

測試用的代碼如下:

let n;  let o = {}, m = new Map();  n = 10000;  while (n--) { o[Math.random()] = Math.random(); }  n = 10000;  while (n--) { m.set(Math.random(), Math.random()); }  let p1 = performance.now();  for (key in o) { delete o[key]; }  let p2 = performance.now();  for ([key] of m) { m.delete(key); }  let p3 = performance.now();  `Object: ${(p2 - p1).toFixed(3)}ms, Map: ${(p3 - p2).toFixed(3)}ms`

對于刪除元素時的速度表現如下:

JavaScript中Object和Map對比實例分析

我們可以發現在進行刪除操作時,Map 的速度會略占優,但整體差別其實并不大。

特殊情況

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

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

在鍵為連續非負整數時,性能如下:

JavaScript中Object和Map對比實例分析

JavaScript中Object和Map對比實例分析

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

到此,關于“JavaScript中Object和Map對比實例分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

湖州市| 德令哈市| 开江县| 绥中县| 芜湖县| 太湖县| 九龙县| 清涧县| 亚东县| 伊川县| 胶州市| 和林格尔县| 大方县| 仙游县| 游戏| 灵川县| 建昌县| 汝城县| 定兴县| 六枝特区| 遂昌县| 攀枝花市| 杭锦后旗| 简阳市| 施甸县| 崇左市| 黄大仙区| 马公市| 宜丰县| 称多县| 临西县| 承德县| 青阳县| 东安县| 临朐县| 阜康市| 璧山县| 纳雍县| 开封市| 太谷县| 卓尼县|