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. 使用 HTML5 Geolocation 构建基于地理位置的 Web 应用学习网站分享

    HTML5 中的新功能 HTML5 是最新一代的 HTML 规范,是 W3C 与 WHATWG 合作的结果,目前仍外于开发中.自从上一代 HTML4,Web 世界已经发生了巨大的变化,HTML5 的到 ...

  2. 与LCD_BPP相关的函数

    board/freescale/mx6q_sabresd/mx6q_sabresd.c:    panel_info.vl_bpix = LCD_BPP; common/lcd.c:   off  = ...

  3. angular中几种加载css的方法

    1.Style URLs in Metadata We can load styles from external CSS files by adding a styleUrls attribute ...

  4. 网址导航[IT]

    一.Linux/UNIX Linux公社:http://www.linuxidc.com/index.htm Linux命令大全:http://man.linuxde.net 伯乐在线:http:// ...

  5. Java-获取堆的大小

    package com.tj; public class getHeapInfo { public static void main(String[] args) { //获取当前堆的大小 byte ...

  6. SPOJ - DQUERY 主席树求区间有多少个不同的数(模板)

    D-query Time Limit: 227MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Submit Status ...

  7. 使用ANT将Android打包成Jar包

    本文主要实现使用ANT,将Android项目打包成jar,为方便其他项目使用. ANT可以去官网下载(http://ant.apache.org/) 先介绍打包的步骤,打包脚本下方贴出 步骤: 1,将 ...

  8. WebLoad XML-parser methods

    WebLOAD provides an embedded, third-party XML parser object to improve the multi-platform support fo ...

  9. 刷题总结——书架(bzoj1861)

    题解: Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然 ...

  10. VB6 post图片

    在VBA中怎样用XMLhttp 模拟http上传二进制文件? https://www.zhihu.com/question/40974557 作者:付杨 链接:https://www.zhihu.co ...