最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用JavaScript的Map提升性能的方法詳解

 更新時間:2019年08月14日 08:26:02   作者:連城  
這篇文章主要介紹了利用JavaScript的Map提升性能的方法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

前言

在ES6中引入JavaScript的新特性中,我們看到了Set和Map的介紹。與常規(guī)對象和Array不同的是,它們是“鍵控集合(keyed collections)”。這就是說它們的行為有稍許不同,并且在特定的上下文中使用,它們可以提供相當(dāng)大的性能優(yōu)勢。

在這篇文章中,我將剖析Map,它究竟有何不同,哪里可以派上用場,相比于常規(guī)對象有什么性能優(yōu)勢。

Map與常規(guī)對象有什么不同

Map和常規(guī)對象主要有2個不同之處。

1.無限制的鍵(Key)

常規(guī)JavaScript對象的鍵必須是String或Symbol,下面的對象說明的這一點(diǎn):

const symbol = Symbol();
const string2 = 'string2';

const regularObject = {
 string1: 'value1',
 [string2]: 'value2',
 [symbol]: 'value3'
};

相比之下,Map允許你使用函數(shù)、對象和其它簡單的類型(包括NaN)作為鍵,如下代碼:

const func = () => null;
const object = {};
const array = [];
const bool = false;
const map = new Map();

map.set(func, 'value1');
map.set(object, 'value2');
map.set(array, 'value3');
map.set(bool, 'value4');
map.set(NaN, 'value5');

在鏈接不同數(shù)據(jù)類型時,這個特性提供了極大的靈活性。

2.直接遍歷

在常規(guī)對象中,為了遍歷keys、values和entries,你必須將它們轉(zhuǎn)換為數(shù)組,如使用Object.keys()、Object.values()和Object.entries(),或者使用for ... in循環(huán),因?yàn)槌R?guī)對象不能直接遍歷,另外for ... in循環(huán)還有一些限制:它僅僅遍歷可枚舉屬性、非Symbol屬性,并且遍歷的順序是任意的。
而Map可以直接遍歷,并且由于它是鍵控集合,遍歷的順序和插入鍵值的順序是一致的。你可以使用for ... of循環(huán)或forEach方法來遍歷Map的entries,如下代碼:

for (let [key, value] of map) {
 console.log(key);
 console.log(value);
};
map.forEach((key, value) => {
 console.log(key);
 console.log(value);
});

還有一個好處就是,你可以調(diào)用map.size屬性來獲取鍵值數(shù)量,而對于常規(guī)對象,為了做到這樣你必須先轉(zhuǎn)換為數(shù)組,然后獲取數(shù)組長度,如:Object.keys({}).length。

Map和Set有何不同

Map的行為和Set非常相似,并且它們都包含一些相同的方法,包括:has、get、set、delete。它們兩者都是鍵控集合,就是說你可以使用像forEach的方法來遍歷元素,順序是按照插入鍵值排列的。
最大的不同是Map通過鍵值(key/value)成對出現(xiàn),就像你可以把一個數(shù)組轉(zhuǎn)換為Set,你也可以把二維數(shù)組轉(zhuǎn)換為Map:

const set = new Set([1, 2, 3, 4]);
const map = new Map([['one', 1], ['two', 2], ['three', 3], ['four', 4]]);

類型轉(zhuǎn)換

要將Map切換回數(shù)組,你可以使用ES6的結(jié)構(gòu)語法:

const map = new Map([['one', 1], ['two', 2]]);
const arr = [...map];

到目前為止,將Map與常規(guī)對象的互相轉(zhuǎn)換依然不是很方便,所以你可能需要依賴一個函數(shù)方法,如下:

const mapToObj = map => {
 const obj = {};
 map.forEach((key, value) => { obj[key] = value });
 return obj;
};
const objToMap = obj => {
 const map = new Map();
 Object.keys(obj).forEach(key => { map.set(key, obj[key]) });
 return map;
};

但是現(xiàn)在,在八月份ES2019的首次展示中,我們看見了Object引入了2個新方法:Object.entries()和Object.fromEntries(),這可以使上述方法簡化許多:

const obj2 = Object.fromEntries(map);
const map2 = new Map(Object.entries(obj));

在你使用Object.fromEntries轉(zhuǎn)換map為object之前,確保map的key在轉(zhuǎn)換為字符串時會產(chǎn)生唯一的結(jié)果,否則你將面臨數(shù)據(jù)丟失的風(fēng)險。

性能測試

為了準(zhǔn)備測試,我會創(chuàng)建一個對象和一個map,它們都有1000000個相同的鍵值。

let obj = {}, map = new Map(), n = 1000000;
for (let i = 0; i < n; i++) {
 obj[i] = i;
 map.set(i, i);
}

然后我使用console.time()來衡量測試,由于我特定的系統(tǒng)和Node.js版本的原因,時間精度可能會有波動。測試結(jié)果展示了使用Map的性能收益,尤其是添加和刪除鍵值的時。

查詢

let result;
console.time('Object');
result = obj.hasOwnProperty('999999');
console.timeEnd('Object');
// Object: 0.250ms

console.time('Map');
result = map.has(999999);
console.timeEnd('Map');
// Map: 0.095ms (2.6 times faster)

添加

console.time('Object');
obj[n] = n;
console.timeEnd('Object');
// Object: 0.229ms

console.time('Map');
map.set(n, n);
console.timeEnd('Map');
// Map: 0.005ms (45.8 times faster!)

刪除

console.time('Object');
delete obj[n];
console.timeEnd('Object');
// Object: 0.376ms

console.time('Map');
map.delete(n);
console.timeEnd('Map');
// Map: 0.012ms (31 times faster!)

Map在什么情況下更慢

在測試中,我發(fā)現(xiàn)一種情況常規(guī)對象的性能更好:使用for循環(huán)去創(chuàng)建常規(guī)對象和map。這個結(jié)果著實(shí)令人震驚,但是沒有for循環(huán),map添加屬性的性能勝過常規(guī)對象。

console.time('Object');
for (let i = 0; i < n; i++) {
 obj[i] = i;
}
console.timeEnd('Object');
// Object: 32.143ms

let obj = {}, map = new Map(), n = 1000000;
console.time('Map');
for (let i = 0; i < n; i++) {
 map.set(i, i);
}
console.timeEnd('Map');
// Map: 163.828ms (5 times slower)

舉個例子

最后,讓我們看一個Map比常規(guī)對象更合適的例子,比如說我們想寫一個函數(shù)去檢查2個字符串是否由相同的字符串隨機(jī)排序。

console.log(isAnagram('anagram', 'gramana')); // Should return true
console.log(isAnagram('anagram', 'margnna')); // Should return false

有許多方法可以做到,但是這里,map可以幫忙我們創(chuàng)建一個最簡單、最快速的解決方案:

const isAnagram = (str1, str2) => {
 if (str1.length !== str2.length) {
  return false;
 }
 const map = new Map();
 for (let char of str1) {
  const count = map.has(char) ? map.get(char) + 1 : 1;
  map.set(char, count);
 }
 for (let char of str2) {
  if (!map.has(char)) {
   return false;
  }
  const count = map.get(char) - 1;
  if (count === 0) {
   map.delete(char);
   continue;
  }
  map.set(char, count);
 }
 return map.size === 0;
};

在這個例子中,當(dāng)涉及到動態(tài)添加和刪除鍵值,無法提前確認(rèn)數(shù)據(jù)結(jié)構(gòu)(或者說鍵值的數(shù)量)時,map比object更合適。

我希望這篇文章對你有所幫助,如果你之前沒有使用過Map,不妨開闊你的眼界,衡量現(xiàn)代JavaScript的價值體現(xiàn)。

譯者注:我個人不太同意作者的觀點(diǎn),從以上的描述來看,Map更像是以空間為代價,換取速度上的提升。那么對于空間和速度的衡量,必然存在一個閾值。在數(shù)據(jù)量比較少時,相比與速度的提升,其犧牲的空間代價更大,此時顯然是不適合使用Map;當(dāng)數(shù)據(jù)量足夠大時,此時空間的代價影響更小。所以,看開發(fā)者如何衡量兩者之間的關(guān)系,選擇最優(yōu)解。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺析如何在Bash中調(diào)用Node運(yùn)行JS文件進(jìn)行數(shù)據(jù)通信

    淺析如何在Bash中調(diào)用Node運(yùn)行JS文件進(jìn)行數(shù)據(jù)通信

    這篇文章主要來和大家探討在 Bash 中調(diào)用 Node 運(yùn)行 JS 文件時如何進(jìn)行數(shù)據(jù)通信,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • 通過javascript實(shí)現(xiàn)掃雷游戲代碼實(shí)例

    通過javascript實(shí)現(xiàn)掃雷游戲代碼實(shí)例

    這篇文章主要介紹了通過javascript實(shí)現(xiàn)掃雷游戲代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • js 如何實(shí)現(xiàn)對數(shù)據(jù)庫的增刪改查

    js 如何實(shí)現(xiàn)對數(shù)據(jù)庫的增刪改查

    JavaScript操作數(shù)據(jù)庫JS操作Access數(shù)據(jù)庫,跟其他語言操作差不多,總結(jié)了一下習(xí)慣代碼,需要的朋友可以參考下
    2012-11-11
  • svg動畫之動態(tài)描邊效果

    svg動畫之動態(tài)描邊效果

    本文主要介紹了svg實(shí)現(xiàn)的動態(tài)描邊效果,文中分享了兩個實(shí)例:1.一個簡單的線一點(diǎn)一點(diǎn)畫出來的效果;2.用同樣的原理畫一個“藍(lán)胖子”。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • Javascript數(shù)組常用方法你都知道嗎

    Javascript數(shù)組常用方法你都知道嗎

    這篇文章主要為大家詳細(xì)介紹了Javascript數(shù)組常用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • Bootstrap popover用法詳解

    Bootstrap popover用法詳解

    這篇文章主要為大家詳細(xì)介紹了Boostrap popover用法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 文檔處理系列——隨時更新

    文檔處理系列——隨時更新

    文檔處理系列——隨時更新...
    2007-07-07
  • js中如何把字符串轉(zhuǎn)化為對象、數(shù)組示例代碼

    js中如何把字符串轉(zhuǎn)化為對象、數(shù)組示例代碼

    在本文為大家介紹下把字符串轉(zhuǎn)化為對象:把文本轉(zhuǎn)化為對象、把文本轉(zhuǎn)化為數(shù)組,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈,希望對大家有所幫助
    2013-07-07
  • 淺析return false的正確使用

    淺析return false的正確使用

    “return false”之所以被誤用的如此厲害,是因?yàn)樗雌饋硐袷峭瓿闪宋覀兘唤o它的工作,瀏覽器不會再將我們重定向到href中的鏈接,表單也不會被繼續(xù)提交,但這么做到底有什么不對呢
    2013-11-11
  • BootstrapTable refresh 方法使用實(shí)例簡單介紹

    BootstrapTable refresh 方法使用實(shí)例簡單介紹

    本文就bootstrapTable refresh 方法如何傳遞參數(shù)做簡單舉例說明,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-02-02

最新評論

河源市| 兴海县| 阿尔山市| 金塔县| 许昌市| 交口县| 班戈县| 洞头县| 文安县| 平遥县| 屯昌县| 东宁县| 花莲县| 呼和浩特市| 阿城市| 定西市| 阳新县| 望谟县| 马鞍山市| 南康市| 门头沟区| 建始县| 鲁山县| 永平县| 花莲市| 上高县| 宾阳县| 施秉县| 永德县| 大安市| 盱眙县| 盐边县| 嘉黎县| 南木林县| 潍坊市| 措美县| 莱阳市| 曲靖市| 巴东县| 吴忠市| 夏河县|