我刚刚发现了此功能:

地图:地图对象是简单的键/值地图。

这让我感到困惑。常规JavaScript对象是字典,那么Map与字典有何不同?从概念上讲,它们是相同的(根据有关Stackoverflow的另一个问题)
文档也无济于事:

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


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

…在我看来还是一个对象,所以显然我错过了一些东西。 Map对象?它是做什么的?

评论

另请参见Javascript Map对象将如何改善我们的编码?

#1 楼

根据mozilla:

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

and

对象与Maps相似,都可以将键设置为值,
检索这些值,删除键,并检测键中是否存储了某些内容。因此,对象在历史上一直被用作地图。但是,对象与地图之间存在重要的区别,使得使用地图更好。
对象具有原型,因此地图中有默认键。
但是,可以绕过此键使用map = Object.create(null)。对象的
键是字符串,在其中它们可以是Map的任何值。
您可以轻松获取Map的大小,而必须手动跟踪对象。
当键在运行时之前是未知的,并且
所有键都是相同的类型且所有值都是相同的类型时,请使用对象上的映射。
在存在可操作的逻辑时使用对象在各个元素上。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
按顺序进行迭代是一项功能开发人员长期以来一直希望这样做,部分原因是它确保了所有浏览器的相同性能。所以对我来说,这是一个很大的问题。
myMap.has(key)方法将特别方便,而且myMap.size属性也将非常方便。

评论


不利的一面是,为了保持插入顺序,映射需要更多的内存(但是在相同的数量级内)。

–约翰·库拉克(John Kurlak)
2014年6月5日18:27

除了这里提到的有序性(使用任何对象作为键,键和道具的分离等)外,地图还具有其他功能,但是在某些情况下FWIW由ES2015定义了普通对象属性的迭代顺序。请参阅stackoverflow.com/a/32149345。

– JMM
2015年10月9日,19:59

当您说“对象具有原型”时,我没有得到这个含义,因此地图中有默认键。但是,可以使用map = Object.create(null)绕过此操作。什么是默认密钥?密钥与Object.prototype有何关系?

–过度兑换
2015年12月30日18:27



我在Chrome浏览器中进行的测试表明,地图在维护顺序方面不会使用任何大量内存。我认为一百万个密钥还有0.1KB,我不认为这是为了维护顺序。但是,〜0.1KB似乎是恒定的开销。如果用一个键创建一百万张地图,然后比较它比对象大得多。

– jgmjgm
16年6月23日在17:38

@luxon,您正在此处创建对象。 ES6规范要求将new运算符与Map符号一起使用,即使用new Map来创建地图对象。 var a = {}是var a = Object.create(Object.prototype)的简写(等于)

– dudewad
17年7月9日在0:13

#2 楼

关键区别在于对象仅支持字符串键和符号键,而Maps或多或少地支持任何键类型。 Map会保留键的类型并返回obj[123] = true,这很好。地图还允许您将对象用作键。传统上,您必须为对象提供某种唯一的标识符以对它们进行哈希处理(我认为我从未见过像JS中的Object.keys(obj)这样的标准)。地图还可以保证顺序的保存,因此可以更好地进行保存,有时可以省去一些需要做的事情。
在实践中,地图和对象之间有很多利弊。将对象紧密地集成到JavaScript内核中既有优缺点,也使它们与明显的Map区别开来,这超出了关键支持上的区别。 。您还可以通过JSON直接支持它。当用作哈希时,获取一个完全没有任何属性的对象很烦人。默认情况下,如果要将Objects用作哈希表,它们将被污染,并且在访问属性时通常必须对其调用["123"]。您可以在此处看到默认情况下如何污染对象以及如何创建希望不受污染的对象以用作哈希:
({}).toString
    toString() { [native code] }
JSON.parse('{}').toString
    toString() { [native code] }
(Object.create(null)).toString
    undefined
JSON.parse('{}', (k,v) => (typeof v === 'object' && Object.setPrototypeOf(v, null) ,v)).toString
    undefined

对对象的污染不仅使代码更烦人,更慢,而且还可以对安全性有潜在的影响。
对象不是纯粹的哈希表,而是试图做更多的事情。您会遇到类似[123]的头痛,无法轻松获取长度([123])等。对象并不是纯粹用作哈希映射,而是动态扩展对象,因此当您将它们用作纯哈希表时,会出现问题。
    Object:
       var o = {};
       var o = Object.create(null);
       o.key = 1;
       o.key += 10;
       for(let k in o) o[k]++;
       var sum = 0;
       for(let v of Object.values(m)) sum += v;
       if('key' in o);
       if(o.hasOwnProperty('key'));
       delete(o.key);
       Object.keys(o).length
    Map:
       var m = new Map();
       m.set('key', 1);
       m.set('key', m.get('key') + 10);
       m.foreach((k, v) => m.set(k, m.get(k) + 1));
       for(let k of m.keys()) m.set(k, m.get(k) + 1);
       var sum = 0;
       for(let v of m.values()) sum += v;
       if(m.has('key'));
       m.delete('key');
       m.size();

还有一些其他选项,方法,方法论等,它们有起伏的变化(性能,简洁,可移植,可扩展等)。对象是语言的核心,所以有点奇怪,因此您有很多静态方法可以使用它们。从物体产生的副作用来看。 Map是纯散列,尝试同时成为一个对象没有任何困惑。使用代理功能还可以轻松扩展地图。对象当前具有Proxy类,但是性能和内存使用情况很糟糕,实际上创建自己的代理看起来像Map for Objects目前比Proxy更好。
Maps的一个主要缺点是JSON不直接支持它们。解析是可能的,但是有一些挂断: JSON编码甚至更加困难且存在问题(这是许多方法之一):
JSON.parse(str, (k,v) => {
    if(typeof v !== 'object') return v;
    let m = new Map();
    for(k in v) m.set(k, v[k]);
    return m;
});

如果仅使用Maps,这还不错,但是当您混合类型或使用非-标量值作为键(不是JSON完美地解决了这种问题,即IE循环对象引用)。我还没有测试过它,但是与stringize相比,它有可能严重损害性能。
其他脚本语言通常不会出现问题,因为它们具有Map,Object和Array的显式非标量类型。对于非标量类型,Web开发通常很麻烦。在这种情况下,您必须处理诸如PHP使用A / M作为属性将Array / Map与Object合并为对象,而JS将Map / Object与Array扩展为M / O合并的情况。合并复杂类型是高级脚本语言的魔咒。
到目前为止,这些主要是实现方面的问题,但是基本操作的性能也很重要。性能也很复杂,因为它取决于引擎和使用情况。用我的盐进行测试,因为我不能排除任何错误(我必须匆忙解决)。您还应该运行自己的测试,以确认我的检查仅是非常具体的简单方案,仅给出粗略的指示。根据针对大型对象/地图的Chrome测试,对象的性能较差,这是因为删除显然与键的数量成比例,而不是与O(1)成比例:在获取和更新方面具有强大的优势,但删除性能令人震惊。在这种情况下(开销),地图使用的内存量很少。但是,只有一个对象/地图已通过数百万个键进行测试,因此无法很好地体现地图开销的影响。使用内存管理对象,如果我正确地读取配置文件,似乎也可以早一点释放,这可能是支持对象的好处。 />我应该立即指出,在此特定的基准测试中,从Firefox中删除对象不会引起任何问题,但是在其他基准测试中,它却引起了问题,尤其是当有很多键(如Chrome)时。对于大型集合来说,地图显然在Firefox中具有优势。
但这还不是故事的结局,那么许多小对象或地图呢?我已经对此进行了快速基准测试,但没有进行详尽的(设置/获取)测试,在上述操作中使用少量的键效果最佳。此测试更多关于内存和初始化。
// An alternative to this it to use a replacer in JSON.stringify.
Map.prototype.toJSON = function() {
    return JSON.stringify({
        keys: Array.from(this.keys()),
        values: Array.from(this.values())
    });
};

同样,这些数字各不相同,但Object基本上领先。在某些情况下,对象在地图上的领先优势是极端的(约好10倍),但平均而言要好2-3倍。似乎极端的性能峰值可以同时起作用。我仅在Chrome浏览器和创建工具中对此进行了测试,以分析内存使用情况和开销。令我惊讶的是,在Chrome浏览器中似乎一键使用的地图比一键使用的对象多30倍的内存。
通过上述所有操作(4个键)测试许多小对象:
Object Set Took: 146
Object Update Took: 7
Object Get Took: 4
Object Delete Took: 8239
Map Set Took: 80
Map Update Took: 51
Map Get Took: 40
Map Delete Took: 2

就内存分配而言,它们在释放/ GC方面表现相同,但Map使用的内存多5倍。该测试使用了4个键,而在上一个测试中,我只设置了一个键,因此可以解释内存开销的减少。我进行了几次测试,从整体速度上来说,Chrome的Map / Object或多或少与脖子并驾齐驱。在Firefox中,小型对象在总体上比地图具有明显的性能优势。我不建议对这些数字进行微优化。您可以从中得到的经验是,根据经验,对于大型键值存储区,最好考虑使用Maps;对于小型键值存储区,最好考虑对象。只需使其首先工作即可。在进行概要分析时,请务必牢记,有时由于对象键删除案例中出现的引擎怪异,您在查看它们时不会觉得很慢的事情可能会变得非常慢。

评论


缺乏可序列化性一直是许多开发人员的真正痛苦。看看“如何在本地存储(或其他地方)中保存ES6映射”的观点。以及如何JSON.stringify ES6 Map?

–于富兰
18年11月20日在18:30

数字是毫秒,字节还是对象总数?

– SteefansArya
20年4月7日在6:25

这样说来,女士(花了一点时间来表示已用过的东西,因此在这种情况下会消耗时间)。尽管这是一个古老的测试,并且我没有基准代码了。现在可能已经非常不同了。例如,我认为删除问题已解决。

– jgmjgm
20-4-8在17:54



尽管Map可以将任何值用作键,但是键查找的语义使用对象引用相等性,而不是使用值语义,这会引起问题。

–雷德瓦尔德
20 Dec 15'在12:14

#3 楼

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


地图可以更大>在chrome中,使用Map可以获得1670万个键/值对,而使用常规对象则可以获得1110万。使用Map几乎增加了50%的配对。它们在崩溃前都占用大约2GB的内存,因此我认为可能与Chrome的内存限制有关(编辑:是的,尝试填充2个Maps,崩溃前每个序列只能得到830万对)。您可以使用以下代码自己进行测试(显然,请分别运行而不是同时运行它们):
这个人以前把我绊倒了。常规对象具有toStringconstructorvalueOfhasOwnPropertyisPrototypeOf和一堆其他预先存在的属性。对于大多数用例来说,这可能不是什么大问题,但以前曾对我造成过麻烦。缺乏内部优化,对于某些任务,Map可能比普通的旧JavaScript对象要慢得多。

评论


您认为语义在这里是否胜过性能?如果您需要字典,地图听起来很完美,但是很难接受较慢的查找。快速查询不是整个词典的重点吗?

–user2954463
17年7月12日在14:39



如果您可以使用1100万个键/值对,并且不关心诸如toString,构造函数等预先存在的键,那么我肯定会选择普通的旧对象(例如,您的键极不可能与它们冲突) )。它们更易于使用-例如增量是obj [i] =(obj [i] || 0)+ 1,而使用Map的是map.set(i,(map.get(i)|| 0)+ 1)还是不错的,但这只是说明事情如何变得不必要的混乱。地图肯定有其用例,但是通常一个普通的对象就可以。

–user993683
17年7月13日在2:15

请注意,您可以通过编写obj = Object.create(null)而不是obj = {}来摆脱默认的toString,构造函数(等)对象属性。

–user10898116
19 Jun 4'6:47



#4 楼

object的行为就像字典一样,因为Javascript是动态键入的,允许您随时添加或删除属性。和Map()方法。
接受键的任何类型,而不仅是字符串。
提供迭代器以方便get的使用并保持结果的顺序。属性在迭代或复制过程中显示。
支持数百万个项目。
非常快。

99%的时间应该只使用set
如果您只使用基于字符串的键并且需要最大的读取性能,那么对象可能是一个更好的选择。
这是因为javascript引擎在后台将对象编译为C ++类。这些类被缓存,因此当您创建具有相同精确属性的新对象时,引擎将重用现有的背景类。这些类上的属性的访问路径经过了优化,并且比has的函数调用要快得多。为什么将对象用作具有大量添加和删除操作的字典非常慢,但是在不更改对象的情况下读取现有键的速度非常快。使用delete作为高性能词典,但对于其他所有内容,请使用for-of

评论


对象也提供获取集具有删除等功能,它不是那么优雅(但也不错)。 Map通过哪种方式更易于迭代?不知道我可以同意。

–安德鲁(Andrew)
20年5月6日在4:20

@Andrew我正在讨论这些方法,并且功能也有所不同,具体取决于您所使用的内容和结果。迭代更容易,因为原型和本机属性不会出现在循环中,而是使用保持相同顺序的普通JS迭代器。

–马尼·甘丹(Mani Gandham)
20年5月6日在8:31

为什么它是99%的时代?如果您的密钥是字符串,或者只是数字。为什么要使用地图?这只是一个对象的实现。是什么使它胜于目标。

–伊多·布莱切(Ido Bleicher)
20年8月29日在12:19

@IdoBleicher答案中列出了原因。地图在功能上更易于使用,遵循预期的行为,并且通常更快。同样,它们不是对象的实现,而是单独的数据结构,这就是它与引擎支持联系在一起的原因。您是否需要进一步澄清?

–马尼·甘丹(Mani Gandham)
20年8月29日在16:12

#5 楼

除了其他答案外,我发现与对象相比,使用Map更麻烦,更冗长。

obj[key] += x
// vs.
map.set(map.get(key) + x)


这很重要,因为较短的代码会更快

另一方面:因为set()返回映射而不是值,所以无法链接分配。

foo = obj[key] = x;  // Does what you expect
foo = map.set(key, x)  // foo !== x; foo === map


调试地图也比较麻烦。在下面,您实际上看不到地图中的键。为此,您必须编写代码。



任何IDE均可评估对象:



评论


考虑到所有这些,似乎map是一个过早的优化。

–PRMan
18年6月15日在20:18

#6 楼

摘要:



Object:一种数据结构,其中的数据作为键值对存储。在对象中,键必须是数字,字符串或符号。该值可以是任何值,其他对象,函数等也可以。对象是无序数据结构,即不记得插入键值对的顺序。
存储为键值对。其中唯一键映射到值。键和值都可以是任何数据类型。映射是可迭代的数据结构,这意味着插入顺序会被记住,并且我们可以访问例如一个ES6 Map循环

主要区别:类型的数据作为for..of的键,而对象只能具有数字,字符串或符号作为键。
Map继承自Map。这提供了各种实用程序功能和属性,使使用Map对象更加容易。

示例:

对象:




 Map.prototype





地图:




 Map





来源:MDN

#7 楼

何时使用Google Maps代替纯JavaScript对象?

纯JavaScript对象{key:'value'}保存结构化数据。但是普通的JS对象有其局限性:


只有字符串和符号可以用作Object的键。如果我们使用其他任何说法,将数字作为对象的键,则在访问这些键期间,我们将看到这些键将隐式转换为字符串,从而使我们失去类型的一致性。 const names = {1:“一个”,2:“两个”}; Object.keys(名称); // ['1','2']
通过将JS标识符写为对象(例如toString,构造函数等)的键名,可能会意外覆盖原型的继承属性。
另一个对象不能用作对象的键,因此不能通过将对象写为另一个对象的键来为该对象写任何额外的信息,而另一个对象的值将包含额外的信息
对象不是迭代器
无法直接确定对象的大小

这些对象的限制已由地图解决,但我们必须将地图视为对象的补充而不是替代。基本上,Map只是数组数组,但我们必须将该数组数组作为带有new关键字的参数传递给Map对象,否则,仅对于数组数组,Map的有用属性和方法不可用。并记住数组数组或Map中的键/值对必须仅用逗号分隔,没有像普通对象中那样的冒号。

3条提示决定使用Map还是Object br />

在直到运行时才知道键的情况下,使用对象上的映射,因为由用户输入或在不知不觉中形成的键会破坏使用该对象的代码,如果这些键覆盖了对象的继承属性,那么在这种情况下,地图会更安全。当所有键都是相同类型并且所有映射都是相同类型时,也要使用映射。
如果需要将原始值存储为键,请使用地图。
如果需要对单个元素进行操作,请使用对象。

使用Maps的好处是:

1。 Map接受任何键类型并保留键类型:

我们知道,如果对象的键不是字符串或符号,则JS会将其隐式转换为字符串。相反,Map接受任何类型的键:字符串,数字,布尔值,符号等。Map保留原始键类型。在这里,我们将数字用作Map内的键,而它仍将是一个数字:有时候,我们可能想存储一些与对象相关的数据,而又不将这些数据附加到对象本身内部,以便我们可以使用精益对象,但希望存储有关该对象的某些信息。在这些情况下,我们需要使用Map,以便我们可以将Object作为键,并将对象的相关数据作为值。

const numbersMap= new Map();

numbersMap.set(1, 'one');

numbersMap.set(2, 'two');

const keysOfMap= [...numbersMap.keys()];

console.log(keysOfMap);                        // [1, 2]


但是,这种方法的缺点是通过键访问值的复杂性,因为我们必须遍历整个数组才能获得所需的值。

const foo= {name: foo};

const bar= {name: bar};

const kindOfMap= [[foo, 'Foo related data'], [bar, 'Bar related data']];


我们可以解决使用正确的Map无法直接访问该值的问题。

function getBy Key(kindOfMap, key) {
    for (const [k, v]  of kindOfMap) {
        if(key === k) {
            return v;
        }
    }
    return undefined;
}

getByKey(kindOfMap, foo);            // 'Foo related data'


我们可以使用WeakMap完成此操作,只需编写const myMap = new WeakMap()。 Map和WeakMap之间的区别在于,WeakMap允许对键(此处为对象)进行垃圾回收,从而防止内存泄漏; WeakMap仅接受对象作为键,而WeakMap减少了方法集。

2。 Map对键名没有限制:

对于纯JS对象,我们可能会意外覆盖从原型继承的属性,这很危险。在这里,我们将覆盖actor对象的toString()属性:该fn使用toString()方法对其进行检查:

const foo= {name: 'foo'};

const bar= {name: 'bar'};

const myMap= new Map();

myMap.set(foo, 'Foo related data');
myMap.set(bar, 'Bar related data');

console.log(myMap.get(foo));            // 'Foo related data'


Map对键名没有任何限制,我们可以使用诸如toString,构造函数等键名。这里,虽然actorMap对象具有名为toString的属性,但是方法toString()继承自原型actorMap对象的完美工作。这是因为用户可以选择自定义字段名称,例如toString,构造函数等。然后,普通对象中的此类键名可能会破坏以后使用该对象的代码。因此,正确的解决方案是将用户界面状态绑定到映射,没有办法破坏该映射:

3。映射是可迭代的:

要迭代普通对象的属性,我们需要Object.entries()或Object.keys()。 Object.entries(plainObject)返回从对象中提取的一组键值对,然后我们可以对这些键和值进行解构,并获得普通键和值的输出。

const actor= {
    name: 'Harrison Ford',
    toString: 'Actor: Harrison Ford'
};


由于地图是可迭代的,这就是为什么我们不需要entry()方法来迭代地图和键的分解的原因,可以直接在地图上完成值数组就像在Map内一样,每个元素都以键值对的数组形式存在,并以逗号分隔。

function isPlainObject(value) {
    return value.toString() === '[object Object]';
}

isPlainObject(actor);        // TypeError : value.toString is not a function

// this is because inside actor object toString property is a string instead of inherited method from prototype


map.keys()返回键上的迭代器,map.values()返回值上的迭代器。

4。我们可以轻松知道Map的大小

我们无法直接确定普通对象中的属性数量。我们需要一个类似于Object.keys()的辅助函数fn,它返回一个包含对象键的数组,然后使用length属性,我们可以获得键的数量或普通对象的大小。

const actorMap= new Map();

actorMap.set('name', 'Harrison Ford');

actorMap.set('toString', 'Actor: Harrison Ford');

function isMap(value) {
  return value.toString() === '[object Map]';
}

console.log(isMap(actorMap));     // true


但是对于Maps,我们可以使用map.size属性直接访问Map的大小。

const userCustomFieldsMap= new Map([['color', 'blue'], ['size', 'medium'], ['toString', 'A blue box']]);


#8 楼

除了可以按定义的顺序进行迭代之外,还可以使用任意值作为键(-0除外),由于以下原因,映射可能会很有用: >规范将地图操作平均强制为亚线性。

任何非愚蠢的对象实现都将使用哈希表或类似方法,因此属性查找平均可能会保持恒定。这样,对象甚至可能比地图更快。但这不是规范所必需的。


对象可能具有令人讨厌的意外行为。例如,假设您没有将任何foo属性设置为一个新创建的对象obj,因此您希望obj.foo返回未定义。但是foo可以是继承自Object.prototype的内置属性。或者,您尝试通过使用分配来创建obj.foo,但是Object.prototype中的某些设置器会运行,而不是存储您的值。好吧,除非某些脚本将Map.prototype弄乱了。并且Object.create(null)也可以使用,但是您将失去简单的对象初始化程序语法。



#9 楼

我遇到了Minko Gechev撰写的this post,它清楚地说明了主要区别。


#10 楼

查找在地图上没有给予太多关注的一个方面。根据规范:

必须使用哈希表或其他
机制来实现Map对象,这些机制平均提供的访问时间在元素数量上是次线性的在集合中。本Map对象规范中使用的数据结构仅用于描述Map对象所需的可观察语义。它并不是要成为可行的实现模型。

对于具有大量项目并且需要进行项目查找的集合,这将极大地提高性能。
TL; DR-未指定对象查找,因此它可以按对象中元素数量的顺序,即O(n)。 Map查找必须使用哈希表或类似的表,因此无论Map大小如何(O(1)),Map查找都是相同的。

评论


请注意,该规范为使用带有O(log(n))查找的二叉搜索树(如C ++的std :: map)之类的东西敞开了大门。同样在实际引擎中,它们都可能被实现为哈希表(对于V8,请参见v8.dev/blog/fast-properties和medium.com/@bpmxmqd/…,以获取有关引擎如何决定使用“慢速”的解释(字典)属性及其对存储的含义(哈希表))

–戴夫
20-10-13在18:27

是的,@ Dave您是正确的。如果使用了哈希映射以外的其他实现,则时间可能不是固定的。但是,我的原始观点仍然是有效的,这似乎在原始问题中被掩盖了。简而言之,如果您有大量项目并且需要定期查找它们,则Map应该是您的首选数据结构。

– C2Dev
20-10-14在20:56



#11 楼

这是我记住它的一种简短方法:KOI


按键。对象键是字符串或符号。映射键也可以是数字(1和“ 1”不同),对象,NaN等。它使用===来区分键,一个例外是NaN !== NaN,但是您可以使用NaN作为键。
定购。记住插入顺序。因此[...map][...map.keys()]具有特定的顺序。
接口。对象:obj[key]obj.a(在某种语言中,[][]=实际上是接口的一部分)。映射具有get()set()has()delete()等。请注意,您可以使用map[123],但可以将其用作普通的JS对象。

#12 楼

根据Mozilla

用示例简短地说明了JavaScript中的对象与地图。

对象-遵循与地图相同的概念,即使用键值对存储数据。但是有一些细微的差异,使map在某些情况下表现更好。该对包括唯一键和映射到该键的值。它有助于防止重复。

键值差异


Map是对象的实例,但反之亦然。




 var map = new Map();
var obj = new Object(); 
console.log(obj instanceof Map);   // false
console.log(map instanceof Object);  // true






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




 var map = new Map();//Empty 
map.set(1,'1');
map.set('one', 1);
map.set('{}', {name:'Hello world'});
map.set(12.3, 12.3)
map.set([12],[12345])

for(let [key,value] of map.entries())
  console.log(key+'---'+value)






在地图中,元素的原始顺序得以保留。对于对象,情况并非如此。




 let obj ={
  1:'1',
  'one':1,
  '{}': {name:'Hello world'},
  12.3:12.3,
  [12]:[100]
}
console.log(obj)




#13 楼

这两个技巧可以帮助您决定使用Map还是Object:


在直到运行时才知道键的情况下以及在所有键都为相同的类型,并且所有值都是相同的类型。
如果需要将原始值存储为键,请使用映射
,因为对象将每个键都视为字符串,或者是其数字值, />布尔值或任何其他原始值。
当存在对单个元素进行操作的逻辑时,请使用对象。

源:
https://developer.mozilla.org/ zh-CN / docs / Web / JavaScript / Guide / Keyed_Collections#Object_and_Map_compared

评论


这些技巧似乎没有什么特别的帮助,尤其是因为按照这些标准将事情划分开来往往不容易。我不明白第一个为什么键/值是相同类型时映射对您有好处。听起来更像是在尝试使用诸如类/结构之类的对象,诸如集合之类的映射。第二篇写得不好,没到重点。这确实意味着在混合了等效字符串类型(“ 1”和1)或需要/想要保留键类型时使用映射。最后一个我认为与第一个相同,它假设您不知道对象是什么,所以它含糊不清。

– jgmjgm
16 Jun 23'17:44