JS中的Map

Map 是一个含有数据的键的集合,跟普通的 Object一样。但是它们最大的差别是Map允许键是任何类型。
关于Map的方法和属性如下:

  • new Map() 创建一个空集合
  • map.set(key, value) 存储含有值的键
  • map.get(key) 根据键来返回值,如果 key 不在 map 里将会返回 undefined
  • map.has(key) 如果key存在则返回 true,否则返回 false
  • map.delete(key) 根据键来删除值
  • map.clear 清空集合
  • map.size 返回当前全部元素的数量

举个例子:

let map = new Map();
map.set('1', 'str1');
map.set(1, 'num1');
map.set(true, 'bool1');

//Map 会保持类型,而不会像Object将键转化为字符串
alert( map.get(1) );   // 'num1'
alert( map.get('1') );  // 'str1'
Map 还可以使用对象作为键

示例:

let john = { name: 'John' };

//创建一个集合可以存储每个游客的来访次数
let visitsCountMap = new Map();

// john 的来访次数是123 
visitsCountMap.set(john, 123);

//读取 john 的来访次数
alert( visitsCountMap.get(john) ); // 123

使用对象作为键是 Map 最出名也是最重要的特点。

Map 是怎么比较键的?

为了测试键的一致性,Map 使用 SameValueZero 算法。它大致上使用严格相等 ===,但不同的是 NaN 被看成是等于 NaN。所以 NaN 也可以被用作键。(这个算法不能被改变或者自定义)

链式调用

每一次调用 map.set 都会返回集合本身,所以我们可以使用:

map.set('1', 'str1').set(1, 'num1').set(true, 'bool1');
Map 迭代

如果要在 map 里使用循环,可以使用以下三个方法:

  • map.keys() 返回所有键的迭代器
  • map.values() 返回所有值的迭代器
  • map.entries() 返回包含所有键值对的迭代器,在 for..of 循环中默认被使用
    示例:
let recipeMap = new Map([
 ['cucumber', 500], 
 ['tomatoes', 350], 
 ['onion', 50]
]);

//迭代键
for (let vegetable of recipeMap.keys()) {
    alert(vegetable); // cucumber, tomatoes, onion
}

//迭代值
for (let amount of recipeMap.values()) {
    alert(amount); // 500, 350, 50
}

//迭代键值对
for (let entry of recipeMap) { // 效果跟 recipeMap.entries() 相同
  alert(entry);  // 依次是 cucumber,500 tomatoes,350  onion,50
}
按顺序插入

迭代的顺序与插入键的顺序相同。Map 会保持相同的顺序,不像普通 Object 不保证顺序。
除此之外,Map 有个内建 forEach 方法,跟 Array 一样:

//对每个 (key, value) 对运行 forEach 函数
recipeMap.forEach( (value, key, map) => {
   alert(`${key}: ${value}`); // cucumber: 500
})
Object.entries: 把对象转化为 map

Map 被创建之后,我们可以传入带有键值对的数组(或其它可迭代的对象)来进行初始化,像这样:

//包含 [key, value] 对的数组
let map = new Map([
  ['1', 'str1'],
  [1, 'num1'],
  [true, 'bool1']
]);
alert( map.get('1') ); 

如果我们有个纯对象,并且想利用这个纯对象来创建 Map,可以使用内建方法 Object.entries(obj),它返回一个具有相同格式的并且带有键值对的数组对象。
示例:

let obj = {
  name: 'John',
  age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') );  // John

这里,Object.entries 返回一个含有键值对的数组:[ ['name','John'], ['age', 30] ]。这就是 Map 所需要的参数格式。

Object.fromEntries: 把 map 转化为对象

我们刚刚已经利用 Object.entries(obj) 把一个纯对象转化成 Map
Object.fromEntries 方法的作用是相反的:给定一个具有 [key, value] 对的数组,它会根据给定数组转化为 Object

let prices = Object.fromEntries([
  ['banana', 1],
  ['orange', 2],
  ['meat', 3]
]);

alert(prices.orange); // 2

我们可以使用 Object.fromEntries 从 Map 中得到一个纯对象。
例如:我们存了数据在 Map 中,但是我们需要把它转给需要纯对象的第三方代码。
示例:

let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 3);

let obj = Object.fromEntries(map.entries()); 

alert(obj.orange); // 2

调用 map.entries() 将返回含有键值对的数组,这刚好是 Object.fromEntries 所需要的格式。
当然,使用下面的方式也是可以的:

let  obj = Object.fromEntries(map);

上面的代码作用是一样的,因为 Object.fromEntries 需要一个可迭代对象作为参数,map 的标准迭代会返回跟 map.entries() 一样的键值对。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容