公交车上荫蒂添的好舒服的电影-公用玩物(np双xing总受)-公用小荡货芊芊-公与妇仑乱hd-攻把受做哭边走边肉楼梯play-古装一级淫片a免费播放口

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

只會(huì)用Object?我想推薦你試試Map

freeflydom
2023年10月25日 15:18 本文熱度 937

導(dǎo)讀

Javascript中,我們經(jīng)常使用Object對(duì)象來(lái)實(shí)現(xiàn)鍵值對(duì)存儲(chǔ)的功能,但是Object有一些缺點(diǎn)和局限性。為了解決這些問(wèn)題,ES6引入了一個(gè)新的數(shù)據(jù)結(jié)構(gòu):MapMap是一個(gè)有序的鍵值對(duì)集合,它可以存儲(chǔ)任意類型的鍵和值,并且提供了許多便捷的方法。

本文將介紹MapObject的基本用法和區(qū)別,并且說(shuō)明為什么更推薦大家使用Map


對(duì)于Object來(lái)說(shuō),增刪鍵值對(duì)的性能比較差。而在MDN中,特別提到Map對(duì)象對(duì)增刪鍵值對(duì)的操作進(jìn)行了優(yōu)化,如圖所示:

為什么

這與Javascript虛擬機(jī)優(yōu)化對(duì)象的方式有關(guān),虛擬機(jī)通過(guò)假定對(duì)象的結(jié)構(gòu)來(lái)優(yōu)化代碼執(zhí)行效率。而Map是專門用于哈希映射的,其中鍵值是動(dòng)態(tài)且不斷變化的。那么至于為什么沒(méi)有對(duì)Object對(duì)象增刪鍵進(jìn)行優(yōu)化的原因感興趣的小伙伴可以閱讀這篇文章

可迭代性

首先,首先,Object沒(méi)有實(shí)現(xiàn)迭代協(xié)議,所以for…of語(yǔ)句并不能直接迭代對(duì)象。這一點(diǎn)在MDN中也有說(shuō)明:

對(duì)象

對(duì)象的遍歷

由于對(duì)象不能使用使用for...of,所以我們只能使用for...in來(lái)遍歷,但是使用for...in的話,會(huì)有如下問(wèn)題:

  • 會(huì)遍歷對(duì)象所有的可枚舉屬性,包括原型鏈上的屬性

  • 遍歷順序不一定按照對(duì)象屬性定義的順序

  • 遍歷的索引為字符串類型的數(shù)字,并不能直接進(jìn)行計(jì)算

下面就舉例說(shuō)明一下這些問(wèn)題

1. 會(huì)遍歷對(duì)象所有的可枚舉屬性,包括原型鏈上的屬性,例如

function Person(name) {

  this.name = name;

}


Person.prototype.sayHello = function() {

  console.log("Hello, I'm " + this.name);

};


var obj = new Person("Tom");


for (const prop in obj) {

    console.log(prop) // name, sayHello

}


可以看到obj除了自身屬性name之外,還會(huì)遍歷到原型鏈上的屬性sayHello。這是因?yàn)?code>sayHello是可枚舉的。
所以,通常我們需要這樣這樣寫:

// 方法一:使用hasOwnProperty()

for (var prop in obj) {

  if (obj.hasOwnProperty(prop)) {

    console.log(prop); // name

  }

}


// 方法二:使用Object.keys()

var keys = Object.keys(obj);

for (var i = 0; i < keys.length; i++) {

  console.log(keys[i]); // name

}


2. 遍歷順序不一定按照對(duì)象屬性定義的順序,例如:

const obj = {

  a: 1,

  b: 2,

  c: 3,

  "1": "one",

  "2": "two",

  "3": "three"

};


for (var key in obj) {

  console.log(key + ": " + obj[key]);

}


這個(gè)在谷歌瀏覽器中會(huì)先遍歷數(shù)字類型的屬性,如圖:

3. 遍歷的索引為字符串類型的數(shù)字,并不能直接進(jìn)行計(jì)算,例如

const obj = {

  1: "one",

  2: "two",

  3: "three"

};


for (const key in obj) {

  console.log(key, typeof key); // 1 string; 2 string; 3 string

}


const arr = [4, 5, 6]

for (const index in arr) {

 console.log(index, typeof index); // 0 string; 1 string; 2 string;

}


Map

如果是Map,你可以使用標(biāo)準(zhǔn)的for循環(huán)、標(biāo)準(zhǔn)的迭代器和使用解構(gòu)來(lái)獲取keyvalue,例如:

const map1 = new Map();


map1.set('a', 1);

map1.set('b', 2);

map1.set('c', 3);


for (const [key, value] of map1) {

 console.log(key, value) // a 1; b 2; c 3

}


對(duì)于對(duì)象,我們還有一個(gè)Object.entries() 來(lái)做類似的事情,盡管它看起來(lái)不是那么流行,但確實(shí)可以

const myObject = {a: 1, b: 2, c: 3}


for (const [key, value] of Object.entries(myObject)) {

 console.log(key, value) // // a 1; b 2; c 3

}


對(duì)于Map,你有更簡(jiǎn)單的辦法直接內(nèi)置迭代:

// 你可以只便利values,keys


for (const value of myMap.values()) {

 console.log(value)

}


for (const key of myMap.keys()) {

 console.log(key)

}


key

內(nèi)置key

當(dāng)我們這樣創(chuàng)建一個(gè)對(duì)象時(shí):

const myMap = {}


myMap.valueOf // => [Function: valueOf]

myMap.toString // => [Function: toString]

myMap.hasOwnProperty // => [Function: hasOwnProperty]

myMap.isPrototypeOf // => [Function: isPrototypeOf]

myMap.propertyIsEnumerable // => [Function: propertyIsEnumerable]

myMap.toLocaleString // => [Function: toLocaleString]

myMap.constructor // => [Function: Object]


盡管對(duì)象看起來(lái)是個(gè)空的,你也可以訪問(wèn)這些屬性,在MDN中也提到了這個(gè)問(wèn)題:

key的順序

Map保留了鍵的順序,我們可以根據(jù)它明確的順序,直接結(jié)構(gòu)出鍵值:

const [[firstKey, firstValue]] = myMap


實(shí)現(xiàn)LRU緩存

用此特性,我們可以實(shí)現(xiàn)一個(gè)O(1)LRU緩存

什么是LRU緩存?
LRU緩存是一種緩存淘汰策略,它的全稱是Least Recently Used,意思是最近最少使用。它的原理是認(rèn)為最近使用過(guò)的數(shù)據(jù)應(yīng)該是有用的,而很久沒(méi)用過(guò)的數(shù)據(jù)應(yīng)該是無(wú)用的,所以當(dāng)緩存滿了時(shí),就優(yōu)先刪除那些很久沒(méi)用過(guò)的數(shù)據(jù),給新數(shù)據(jù)騰出空間
那么我們用Map實(shí)現(xiàn)一下LRU緩存

class LRUCache {

  constructor(capacity) {

    this.capacity = capacity; // 緩存容量

    this.map = new Map(); // 使用Map存儲(chǔ)鍵值對(duì)

  }


  // 獲取鍵對(duì)應(yīng)的值,如果不存在則返回 -1

  get(key) {

    if (this.map.has(key)) {

      let value = this.map.get(key);

      this.map.delete(key); // 刪除該鍵值對(duì)

      this.map.set(key, value); // 將該鍵值對(duì)重新插入到Map末尾,表示最近使用過(guò)

      return value;

    } else {

      return -1;

    }

  }


  // 設(shè)置或更新鍵和值,如果超過(guò)緩存容量,則刪除最久未使用的鍵值對(duì)

  put(key, value) {

    if (this.map.has(key)) {

      this.map.delete(key);

    } else if (this.map.size >= this.capacity) { // 如果Map中沒(méi)有該鍵,且已達(dá)到緩存容量上限

      let oldestKey = this.map.keys().next().value; // 獲取Map中第一個(gè)(最久未使用)的鍵

      this.map.delete(oldestKey);

    }

    this.map.set(key, value); // 將新的或更新的鍵值對(duì)插入到Map末尾,表示最近使用過(guò) 

  }

}


key的類型

Map甚至可以做一些對(duì)象實(shí)現(xiàn)不了的事情:

myMap.set({}, value)

myMap.set([], value)

myMap.set(document.body, value)

myMap.set(function() {}, value)

myMap.set(myDog, value)


Object中,key必須是字符串、數(shù)字或者Symbol類型,而在Map中則可以是任何類型,包括函數(shù)、對(duì)象或者任何原始值。這意味著,在Map中,我們可以用一個(gè)Object來(lái)作為一個(gè)元素的key

復(fù)制與轉(zhuǎn)換

復(fù)制

你可能會(huì)覺(jué)得對(duì)象更容易復(fù)制,比如:

const copied = {...myObject}

const copied = Object.assign({}, myObject)


但,實(shí)際上Map也容易復(fù)制:

js復(fù)制代碼const copied = new Map(myMap)


同樣,你還可以使用structuredClone 深拷貝:

const copied = new Map(myMap)


轉(zhuǎn)換

// Map轉(zhuǎn)對(duì)象

const myObj = Object.fromEntries(myMap)


// 對(duì)象轉(zhuǎn)Map

const myMap = new Map(Object.entries(myObj))


因此,我們可以不使用元組構(gòu)造映射,可以將它們構(gòu)造成對(duì)象,這樣看起來(lái)更加美觀:

const myMap = new Map([['key', 'value'], ['keyTwo', 'valueTwo']])


// 可以寫成

const myMao = new Map(Object.entries({

    key: 'value',

    keyTwo: 'valueTwo'

}))


序列化與反序列化

現(xiàn)在您可能會(huì)說(shuō)普通對(duì)象和數(shù)組相對(duì)于映射和集合還有最后一個(gè)優(yōu)勢(shì) — 序列化JSON.stringify()JSON.parse()

但是,當(dāng)我們使用時(shí),有個(gè)第二個(gè)參數(shù)傳null: JSON.stringify(obj, null, 2) ,為什么呢?
它被稱為替換器,它允許我們定義任何自定義類型應(yīng)該如何序列化。所以,我們可以輕松的將Map進(jìn)行序列化:

JSON.stringify(obj, (key, value) => {

  // Convert maps to plain objects

  if (value instanceof Map) {

    return Object.fromEntries(value)

  }

  return value

})


我們還可以用相反的方式將對(duì)象轉(zhuǎn)回Map:

JSON.parse(string, (key, value) => {

  if (value && typeof value === 'object') {

    return new Map(Object.entries(value))

  }

  return value

})



查看原文



該文章在 2023/10/25 15:18:57 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产av午夜福利写真电影 | 国产精品偷伦视频免费手机播放 | 国产丝袜足交在线观看 | 国产v亚洲v天堂无码久久 | 成年午夜一级毛片视频 | 国产免费人成在线视频 | 国产做爰xxxⅹ高潮野外 | 国产在线播放成人午夜精品 | 国产熟女真实乱精品 | 国产专区无码午夜 | 高h纯肉无码视频在线观看 高h短篇辣肉各种姿势自慰h | 国产精品天干天干在线综合 | 国产女主播精品大秀系列 | 成人精品一区 | 国产超碰97人人在线 | 国产精品欧美一区麻豆系列 | 国产精品白嫩极品久久久久 | 国产精品女人呻吟在线观看 | 国产成年无码av片在线韩国 | 国产一区二三区好的精华液 | 国产自拍精品在线观看 | 成人午夜做受视欧美频 | 2025男人的天堂网 | 国产宾馆精品在线播放 | 精品国产sm最大网站起碰 | 国产3p一区二区三区视频在线 | 2025国精产品一二三四区 | 国产av无码专区亚洲a√ | 91久久中文精品无码中文字幕 | 国产精品视频全国免费 | 91精品国产亚洲爽啪在线观看 | 99精品国产自产在线观看 | av无码一级毛片免费 | 国产一区亚洲一区 | 国产精品亚洲第一区在线观看 | 国产av午夜精品一区二区入口 | 国产三级在线播放线 | 国产午夜爽爽窝窝在线观看 | 3d动漫精品啪啪一区二区免费 | 国产午夜福利综合区 | 精品国产一区二区三区2025 |