Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

语法

new Map([iterable])

参数

iterable
Iterable 可以是一个数组或者其他 iterable 对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Map。null 会被当做 undefined。

描述

一个Map对象以插入顺序迭代其元素 — 一个  for...of 循环为每次迭代返回一个[key,value]数组。

键的相等(Key equality)

键的比较是基于 "same-value" 算法:NaN 是与 NaN 相同的(虽然 NaN !== NaN),剩下所有其它的值是根据 === 运算符的结果判断是否相等。在 ECMAScript 6 草稿的早期版本中视 -0 和 +0 为不相同的 (虽然 -0 === +0),在近期版本里这个问题已经被更正,且在 Gecko 29 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26) (bug 952870) 和近期的 nightly Chrome 版本这个已经更改了。

Objects 和 maps 的比较

Object 和 Map类似的一点是,它们都允许你按键存取一个值,都可以删除键,还可以检测一个键是否绑定了值.因此,一直以来,我们都把对象当成Map来使用,不过,现在有了Map,下面的区别解释了为什么使用Map更好点.

  • 一个对象通常都有自己的原型,所以一个对象总有一个"prototype"键。不过,从 ES5 开始可以使用 map = Object.create(null)来创建一个没有原型的对象。
  • 一个对象的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
  • 你可以通过size属性很容易地得到一个Map的键值对个数,而对象的键值对个数只能手动确认。

但是这并不意味着你可以随意使用 Map,对象仍旧是最常用的。Map 实例只适合用于集合(collections),你应当考虑修改你原来的代码——先前使用对象来对付集合的地方。对象应该用其字段和方法来作为记录的。
如果你不确定要使用哪个,请思考下面的问题:

  • 在运行之前 key 是否是未知的,是否需要动态地查询 key 呢?
  • 是否所有的值都是统一类型,这些值可以互换么?
  • 是否需要不是字符串类型的 key ?
  • 键值对经常增加或者删除么?
  • 是否有任意个且非常容易改变的键值对?
  • 这个集合可以遍历么(Is the collection iterated)?

假如以上全是“是”的话,那么你需要用 Map 来保存这个集。 相反,你有固定数目的键值对,独立操作它们,区分它们的用法,那么你需要的是对象。

属性

Map.length
属性 length 的值为 0 。
get Map[@@species]
本构造函数用于创建派生对象。
Map.prototype
表示 Map 构造器的原型。 允许添加属性从而应用于所有的 Map 对象。

Map 实例

所有的 Map 对象实例都会继承 Map.prototype。

属性

Map.prototype.constructor
返回一个函数,它创建了实例的原型。默认是Map函数。
Map.prototype.size
返回Map对象的键/值对的数量。

方法

Map.prototype.clear()
移除Map对象的所有键/值对 。
Map.prototype.delete(key)
移除任何与键相关联的值,并且返回该值,该值在之前会被Map.prototype.has(key)返回为true。之后再调用Map.prototype.has(key)会返回false。
Map.prototype.entries()
返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。
Map.prototype.forEach(callbackFn[, thisArg])
按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。如果为forEach提供了thisArg,它将在每次回调中作为this值。
Map.prototype.get(key)
返回键对应的值,如果不存在,则返回undefined。
Map.prototype.has(key)
返回一个布尔值,表示Map实例是否包含键对应的值。
Map.prototype.keys()
返回一个新的 Iterator对象, 它按插入顺序包含了Map对象中每个元素的键 。
Map.prototype.set(key, value)
设置Map对象中键的值。返回该Map对象。
Map.prototype.values()
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。
Map.prototype[@@iterator]()
返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。

示例

使用映射对象

var myMap = new Map();

var keyObj = {},
keyFunc = function () {},
keyString = "a string"; // 添加键
myMap.set(keyString, "和键'a string'关联的值");
myMap.set(keyObj, "和键keyObj关联的值");
myMap.set(keyFunc, "和键keyFunc关联的值"); myMap.size; // 3 // 读取值
myMap.get(keyString); // "和键'a string'关联的值"
myMap.get(keyObj); // "和键keyObj关联的值"
myMap.get(keyFunc); // "和键keyFunc关联的值" myMap.get("a string"); // "和键'a string'关联的值"
// 因为keyString === 'a string'
myMap.get({}); // undefined, 因为keyObj !== {}
myMap.get(function() {}) // undefined, 因为keyFunc !== function () {}

将NaN作为映射的键

NaN 也可以作为Map对象的键. 虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true), 但下面的例子表明, 两个NaN作为Map的键来说是没有区别的:

var myMap = new Map();
myMap.set(NaN, "not a number"); myMap.get(NaN); // "not a number" var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"

使用for..of方法迭代映射

映射也可以使用for..of循环来实现迭代:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
// 将会显示两个log。一个是"0 = zero"另一个是"1 = one" for (var key of myMap.keys()) {
console.log(key);
}
// 将会显示两个log。 一个是 "0" 另一个是 "1" for (var value of myMap.values()) {
console.log(value);
}
// 将会显示两个log。 一个是 "zero" 另一个是 "one" for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
// 将会显示两个log。 一个是 "0 = zero" 另一个是 "1 = one"

使用forEach()方法迭代映射

映射也可以通过forEach()方法迭代:

myMap.forEach(function(value, key) {
console.log(key + " = " + value);
}, myMap)
// 将会显示两个logs。 一个是 "0 = zero" 另一个是 "1 = one"

映射与数组对象的关系

var kvArray = [["key1", "value1"], ["key2", "value2"]];

// 使用映射对象常规的构造函数将一个二维键值对数组对象转换成一个映射关系
var myMap = new Map(kvArray); myMap.get("key1"); // 返回值为 "value1" // 使用展开运算符将一个映射关系转换成一个二维键值对数组对象
console.log(uneval([...myMap])); // 将会向您显示和kvArray相同的数组 // 或者使用展开运算符作用在键或者值的迭代器上,进而得到只含有键或者值得数组
console.log(uneval([...myMap.keys()])); // 输出 ["key1", "key2"]

规范

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
Map
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
Map
Living Standard  

浏览器兼容情况

Feature Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Basic support

38 [1]

12 13 (13) 11 25 7.1
Constructor argument: new Map(iterable) 38 12 13 (13) 未实现 25 9
iterable 38 12 17 (17) 未实现 25 7.1
Map.clear() 31
38
12 19 (19) 11 25 7.1
Map.keys(), Map.values(), Map.entries() 37
38
12 20 (20) 未实现 25 7.1
Map.forEach() 36
38
12 25 (25) 11 25 7.1
Key equality for -0 and 0 34
38
12 29 (29) 未实现 25 9
Constructor argument: new Map(null) (Yes) 12 37 (37) 11 (Yes) 9
Monkey-patched set() in Constructor (Yes) 12 37 (37) 未实现 (Yes) 9
Map[@@species] 51 13 41 (41) 未实现 38 10
Map() without new throws (Yes) 12 42 (42) 11 (Yes) 9

[1] Starting with Chrome 31,the feature was available behind a preference. In chrome://flags, activate the entry “Enable Experimental JavaScript”.

Map与object的区别的更多相关文章

  1. JavaScript Map 和 Object 的区别

    不同点 Key filed 在 Object 中, key 必须是简单数据类型(整数,字符串或者是 symbol),而在 Map 中则可以是 JavaScript 支持的所有数据类型,也就是说可以用一 ...

  2. map泛型 map不指定泛型 与 Map<Object,Object>的区别

    map泛型 map不指定泛型 与 Map<Object,Object>的区别 private void viewDetail(){ Map map1 = new HashMap(); Ma ...

  3. Java不定参数Object… obj 和 Object[] 的区别

    Java不定参数Object… obj 和 Object[] 的区别 简述: java中方法重载可以实现参数不同自动匹配对应方法.但现实中也存在这种问题.普通传参对于形如下面的方法,却显得臃肿而失优雅 ...

  4. HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

    HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的 ...

  5. js es6 map 与 原生对象区别

    区别 object和Map存储的都是键值对组合.但是: object的键的类型是 字符串: map的键的类型是 可以是任意类型: 另外注意,object获取键值使用Object.keys(返回数组): ...

  6. JavaBean与Map<String,Object>相互转换

    一.为什么要实现javaBean与Map<String,Object>相互转换 Spring中的BaseCommandController对象可以将传递过来的参数封装到一个JavaBean ...

  7. ES6 一种新的数据结构--Map跟Objct的区别

    var map1=new Map(); var keys={key:'val'}; map1.set(keys,'content'); ==> {Object {key: "val&q ...

  8. Array、Set、Map、Object学习总结

    Array和Set对比 都是一个存储多值的容器,两者可以互相转换,但是在使用场景上有区别.如下: Array的indexOf方法比Set的has方法效率低下 Set不含有重复值(可以利用这个特性实现对 ...

  9. for, for in, for of, map, forEach 循环的区别:

    for, for in,  for of, map, forEach 循环的区别: for  遍历数组: //对象遍历数组 var arr = [ {Monday: '星期一', Tuesday: ' ...

随机推荐

  1. vue-ssr 文档备注

    https://ssr.vuejs.org/zh/universal.html 基本用法 通过vue-server-renderer插件的createRenderer方法创建一个renderer,再调 ...

  2. 《UNIX环境高级编程》笔记——4.文件和目录

    一.引言 本章描述文件系统的其他特征和文件的性质.有些背景知识需要注意,例如用户ID与文件权限.文件系统等. 二.函数stat.fstat.fstatat和lstat #include <sys ...

  3. Django 模版语法 三

    使用自定义simple_tag 在 app01 下面创建 templatetags 文件夹,在创建 my_tag.py 文件,内容如下: from django import template fro ...

  4. PAT Basic 1035

    1035 插入与归并 根据维基百科的定义: 插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列.每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置.如此迭代直到全部元素有序 ...

  5. PAT Basic 1033

    1033 旧键盘打字 旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 行中分别给出坏掉 ...

  6. java读写串口数据

    本博文参考自https://www.cnblogs.com/Dreamer-1/p/5523046.html 最近接触到了串口及其读写,在此记录java进行串口读写的过程. 1.导入串口支持包 需要下 ...

  7. Hive中文注释乱码解决方案

    本文来自网易云社区 作者:王潘安 快速解决方法 目前的hive客户端在执行desc tablexxx和show create table xxx命令的时候,字段的中文注释会出现乱码情况,如(????) ...

  8. 原 jmeter中类似lr的场景设置

    有一天如果你们领导来一句给我测下这个首页到底能扛多少并发,并发量极限是多少,这时你不要慌不要忙,拿出jmeter神器,设置下场景,目标设置成1000,每10秒启动100个并发,等着看什么时候系统响应开 ...

  9. 被忽视的控件UIToolbar

    前言 UIToolbar以前也接触过,不过没有怎么用,久而久之就忘了他的存在,今天看别人源码的时候看见了,它怎么很方便,在排列一排视图的时候不需要我们算里面的坐标就可以轻松良好的把布局做出来 代码 U ...

  10. c++ primer note

    ---恢复内容开始--- 1.decltype 2.auto 3.cbegin 4.cend 5.constexpr 6.(*Parray)[10]=&arr; //Parray 指向一个含有 ...