我刚刚发现了这个特点:

Map: Map对象是简单的键/值映射。

这让我很困惑。常规JavaScript对象是字典,那么Map与字典有什么不同呢?从概念上讲,它们是相同的(根据Stack Overflow的另一个问题)

文档也没有帮助:

Map对象是键/值对的集合,其中键和值都可以是任意的ECMAScript语言值。不同的键值只能出现在Map集合中的一个键/值对中。使用创建Map时选择的比较算法进行区分的不同键值。

Map对象可以按插入顺序迭代其元素。Map对象必须使用哈希表或其他机制来实现,这些机制提供的访问时间平均与集合中元素的数量呈次线性关系。本Map对象规范中使用的数据结构仅用于描述Map对象所需的可观察语义。它并不是一个可行的实现模型。

听起来还是像个物件,显然我错过了什么。

为什么JavaScript获得一个(受良好支持的)Map对象?它能做什么?


当前回答

这是我记住它的一个简单方法:KOI

Keys. Object key is strings or symbols. Map keys can also be numbers (1 and "1" are different), objects, NaN, etc. It uses === to distinguish between keys, with one exception NaN !== NaN but you can use NaN as a key. Order. The insertion order is remembered. So [...map] or [...map.keys()] has a particular order. Interface. Object: obj[key] or obj.a (in some language, [] and []= are really part of the interface). Map has get(), set(), has(), delete() etc. Note that you can use map[123], but that is using it as a plain JavaScript object.

其他回答

我认为到目前为止答案中还没有提到以下几点,我认为它们值得一提。


地图可以更大

在Chrome中,我可以使用Map获得1670万个键/值对,而使用常规对象可以获得1110万个键/值对。带地图的情侣数量几乎增加了50%。它们在崩溃前都占用了大约2gb的内存,所以我认为可能与chrome的内存限制有关(是的,尝试填充2个地图,在崩溃前你只能得到830万对)。你可以用下面的代码自己测试它(显然,分开运行它们,而不是同时运行):

var m = new Map();
var i = 0;
while(1) {
    m.set(((10**30)*Math.random()).toString(36), ((10**30)*Math.random()).toString(36));
    i++;
    if(i%1000 === 0) { console.log(i/1000,"thousand") }
}
// versus:
var m = {};
var i = 0;
while(1) {
    m[((10**30)*Math.random()).toString(36)] = ((10**30)*Math.random()).toString(36);
    i++;
    if(i%1000 === 0) { console.log(i/1000,"thousand") }
}

对象已经有了一些属性/键

这个问题以前让我犯过错误。常规对象有toString, constructor, valueOf, hasOwnProperty, isPrototypeOf和其他一堆预先存在的属性。对于大多数用例来说,这可能不是一个大问题,但它曾经给我带来过问题。

地图会变慢:

由于.get函数调用开销和缺乏内部优化,Map在某些任务中可能比普通的旧JavaScript对象慢得多。

根据Mozilla

JavaScript中对象与地图的简短示例。

Object-遵循与map相同的概念,即使用键值对存储数据。但也有细微的差异,使得地图在某些情况下表现更好。

Map-是一种数据结构,有助于以对的形式存储数据。这一对由一个唯一键和映射到该键的值组成。这有助于防止口是心非。

关键的不同点

Map是对象的实例,反之则不然。

var map = new map (); var obj = new Object(); console.log(obj instanceof Map);/ /错误 console.log(映射实例对象);/ /正确的

在Object中,键字段的数据类型被限制为整数、字符串和符号。而在Map中,键字段可以是任何数据类型(整数、数组、对象)

var map = new map();//空 map.set (1, ' 1 '); 地图。(' 1 ', 1); 地图。set('{}', {name:'Hello, World!'}); map.set (12.3, 12.3) map.set([12]、[12345]) (let [key,value] of map.entries()) console.log(键+“-”+值)

在Map中,元素的原始顺序被保留。这在对象的情况下是不正确的。

让obj ={ 1: ' 1 ', “一”:1、 '{}': {name:'Hello world'}, 12.3:12.3, [12]: [100] } console.log (obj)

对象的行为类似于字典,因为JavaScript是动态类型的,允许您随时添加或删除属性。

但是Map()更好,因为它:

提供get、set、has和delete方法。 接受任何类型的键,而不仅仅是字符串。 提供一个易于for-of使用的迭代器,并维护结果的顺序。 在迭代或复制过程中不会出现原型和其他属性的边缘情况。 支持数百万项。 非常快。

如果需要字典,则使用Map()。

但是,如果您只使用基于字符串的键,并且需要最大的读取性能,那么对象可能是更好的选择。这是因为JavaScript引擎在后台将对象编译为c++类,并且属性的访问路径比Map().get()的函数调用要快得多。

这些类也被缓存,所以创建一个具有完全相同属性的新对象意味着引擎将重用一个现有的后台类。添加或删除属性会导致类的形状改变,并重新编译支持类,这就是为什么将一个对象用作添加和删除大量内容的字典会非常慢,但是在不更改对象的情况下读取现有键会非常快。

因此,如果您有一个写一次读的繁重的工作负载和字符串键,那么您可以使用对象作为高性能的字典,但对于其他所有事情使用Map()。

TL;DR:你不能在对象中使用键' length'来存储值,但在Map中可以。

对于我来说,不使用object而使用Map的实际考虑是,从实际的角度来看,object的键不是字符串或数字,而是字符串或数字的子集。具体来说,使用与原型的属性名或众所周知的属性冲突的键可能会导致问题。例如,存储具有键长度的值可能会使使用length键来确定给定对象是否为数组的代码混淆。

根据MDN:

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

and

Objects are similar to Maps in that both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. Because of this, Objects have been used as Maps historically; however, there are important differences between Objects and Maps that make using a Map better. An Object has a prototype, so there are default keys in the map. However, this can be bypassed using map = Object.create(null). The keys of an Object are Strings, where they can be any value for a Map. You can get the size of a Map easily while you have to manually keep track of size for an Object.

Map

按顺序迭代是开发人员一直想要的功能,部分原因是它可以确保在所有浏览器中都具有相同的性能。所以对我来说,这是一个大问题。

myMap.has(key)方法将特别方便,还有myMap.has(key)方法。大小属性。