ES6中的地图与对象,何时使用?

时间:2015-09-16 05:02:55

标签: javascript ecmascript-6 javascript-objects

Ref: MDN Maps

  

在密钥未知时直到运行时和何时使用映射到对象上   所有键都是相同的类型,所有值都是相同的类型。

     

当存在对各个元素进行操作的逻辑时使用对象。

问题:

在对象上使用地图的适用示例是什么?特别是“什么时候直到运行时才会知道密钥?”

var myMap = new Map();

var keyObj = {},
    keyFunc = function () { return 'hey'},
    keyString = "a string";

// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

console.log(myMap.get(keyFunc));

6 个答案:

答案 0 :(得分:46)

  

在对象上使用地图的适用示例是什么?

我认为您已经给出了一个很好的例子:当您使用对象(包括Function对象)作为键时,至少需要使用Map

  

特别是"什么时候直到运行时才会知道密钥?"

每当编译时都不知道它们。简而言之,当您需要key-value collection时,应始终使用Map。您需要集合的一个好指标是当您从集合中动态添加和删除值时,尤其是当您事先不知道这些值时(例如,他们从数据库中读取,由用户输入,等)。

相比之下,当您知道对象在编写代码时具有多少属性以及它们的形状是静态时,您应该使用对象。正如@Felix所说:当你需要record时。需要的一个很好的指标是当字段具有不同类型时,以及何时您不需要使用括号表示法(或期望其中有一组有限的属性名称)。

答案 1 :(得分:24)

我认为,对于ES2015的Map,只有两个原因可以使用普通对象:

财产订单何时不重要?

  • 如果您只有一个值和一些应与其明确关联的函数(例如Promise - 这是未来值的代理 - 以及then / catch
  • 如果你有一个结构/类似记录的数据结构,其中包含一个静态的属性集,在#34;编译时" (通常结构/记录不可迭代)

在所有其他情况下,您可以考虑使用Map,因为它保留了属性顺序并将程序(分配给Map对象的所有属性)与数据级别分开({{{{1}中的所有条目1}}本身)。

Map有什么缺点?

  • 你失去了简洁的对象文字语法
  • 您需要JSON.stringyfy
  • 的自定义替换程序
  • 你失去了解构,无论如何对静态数据结构更有用

答案 2 :(得分:10)

  

当密钥未知时直到运行时,并且当所有键都是相同类型且所有值都是相同类型时,才使用映射到对象上。

我不知道为什么有人会写一些明显错误的东西。我不得不说,人们现在在MDN上发现越来越多的错误和/或可疑的内容。

该句中没有任何内容是正确的。使用地图的主要原因是您需要对象值键。价值观应该是同一类型的想法是荒谬的 - 当然,它们可能也是如此。在运行时直到键未知时才应该使用对象的想法同样荒谬。

答案 3 :(得分:4)

MapObject之间的区别之一是:

Map可以使用复杂数据类型作为其关键字。像这样:

const fn = function() {}
const m = new Map([[document.body, 'stackoverflow'], [fn, 'redis']]);

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'

注意:对于复杂数据类型,如果要获取该值,则必须传递与该键相同的引用。

Object,它只接受简单数据类型(numberstring)作为其关键字。

const a = {};
a[document.body] = 'stackoverflow';

console.log(a) //{[object HTMLBodyElement]: "stackoverflow"}

答案 4 :(得分:2)

此问题与重复,但在关闭之前,此处为my answer from over there

除了其他答案之外,我发现地图比对象操作更笨拙和冗长。

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

这很重要,因为更短的代码更快阅读,更直接的表达,更好kept in the programmer's head

另一个方面:因为set()返回地图而不是值,所以不可能链接分配。

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

调试地图也比较痛苦。下面,您实际上无法看到地图中的键。你必须编写代码才能做到这一点。

Good luck evaluating a Map Iterator

任何IDE都可以评估对象:

WebStorm evaluating an object

答案 5 :(得分:0)

ObjectMap相似,两者都使您可以将键设置为值,检索这些值,删除键并检测是否在键处存储了某些内容。因此(并且由于没有内置的替代方法),Object一直以来都被用作Map的名称;但是,在某些情况下,使用Map有一些重要的区别:

  • Object的键是StringSymbol,而它们可以是 Map的任何值,包括函数,对象和任何基元。
  • Map中的键是有序的,而添加到对象的键则没有顺序。从而, 在其上进行迭代时,Map对象按以下顺序返回键: 插入。
  • 通过Map属性,您可以轻松获得size的大小,而 Object中的属性数量必须手动确定。
  • Map是可迭代的,因此可以直接迭代,而 遍历Object要求以某种方式获取其密钥 并遍历它们。
  • 一个Object有一个原型,因此地图中存在默认键 如果您不小心,可能会撞到您的钥匙。从ES5开始 可以通过使用map = Object.create(null)来绕过,但这是 很少完成。
  • Map在涉及频繁添加和 删除密钥对。

MDN