Javascript 在ES6中映射与对象,何时使用?

Javascript 在ES6中映射与对象,何时使用?,javascript,ecmascript-6,javascript-objects,Javascript,Ecmascript 6,Javascript Objects,当关键点在运行时之前未知时,以及 所有键都是相同的类型,所有值都是相同的类型 当存在对单个元素进行操作的逻辑时,使用对象 问题: 在对象上使用贴图的适用示例是什么?特别是,“什么时候密钥在运行时之前是未知的?” 在对象上使用贴图的适用示例是什么 我认为您已经给出了一个很好的示例:当您使用对象(包括函数对象)作为键时,至少需要使用Maps 特别是,“什么时候在运行时之前密钥是未知的?” 当编译时不知道它们时。简而言之,当您需要地图时,应始终使用地图。当您从集合中动态添加和删除值时,尤其是当您事先不

当关键点在运行时之前未知时,以及 所有键都是相同的类型,所有值都是相同的类型

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

问题: 在对象上使用贴图的适用示例是什么?特别是,“什么时候密钥在运行时之前是未知的?”

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

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

特别是,“什么时候在运行时之前密钥是未知的?”

当编译时不知道它们时。简而言之,当您需要地图时,应始终使用地图。当您从集合中动态添加和删除值时,尤其是当您事先不知道这些值时(例如,这些值是从数据库读取的,由用户输入的,等等),可以很好地指示您需要集合

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

当关键点在运行时之前是未知的,并且所有关键点都是相同类型且所有值都是相同类型时,在对象上使用贴图

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


那句话没有一句是正确的。使用贴图的主要原因是需要对象值键时。这些值应该是同一类型的想法是荒谬的——尽管它们当然可能是。在运行时之前密钥未知的情况下不应该使用对象的想法同样荒谬。

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

  • 您根本不想迭代对象类型的属性
  • 或者您可以这样做,但属性顺序并不重要,您可以在迭代时这样做
什么时候财产秩序不重要

  • 如果您只有一个值和一些应该显式关联的函数(如
    Promise
    -它是未来值的代理-和
    ,那么
    /
    catch
  • 如果您有一个类似于结构/记录的数据结构,其中包含一组在“编译时”已知的静态属性(通常结构/记录是不可编译的)

在所有其他情况下,您可以考虑使用<代码> MAP>代码>,因为它保留了属性顺序,并将程序(所有属性分配给<代码> map < /Cord>对象)从数据级别(在map /<代码>本身中的所有条目)。

Map
的缺点是什么

  • 您将失去简明的对象文字语法
  • 您需要JSON.stringyfy的自定义替换程序
  • 您将失去对静态数据结构更有用的分解功能

这个问题是重复的,但在结束之前,这里是:

除了其他答案外,我还发现,与对象相比,映射操作起来更笨拙、更冗长

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
可以使用复杂数据类型作为其键。像这样:

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

m.get(document.body) // 'stackoverflow'
m.get(fn) //'redis'
注意:对于复杂数据类型,如果要获取值,必须传递与键相同的引用

对象
,它只接受简单数据类型(
数字
字符串
)作为键

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

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

Object
s与
Map
s类似,都允许您将键设置为值,检索这些值,删除键,并检测某个键是否存储了内容。因此(并且由于没有内置的替代方案),
对象
s在历史上一直被用作
映射
s;但是,在某些情况下,使用
地图
有一些重要的区别:

  • 对象
    的键是
    字符串
    s和
    符号
    s,而它们可以是
    映射的任何值,包括函数、对象和任何基元
  • Map
    中的键是有序的,而添加到对象中的键不是有序的。因此 当对其进行迭代时,
    Map
    对象按顺序返回键 插入
  • 您可以使用
    size
    属性轻松获取
    Map
    的大小,而
    对象中的属性数必须手动确定
  • Map
    是一个iterable,因此可以直接迭代,而 迭代
    对象
    需要以某种方式获取其键 并对它们进行迭代
  • 对象
    有一个原型,因此地图中有默认键 如果你不小心,可能会与你的钥匙相撞。从ES5开始 可以通过使用
    map=Object.create(null)
    绕过,但这是 很少做
  • Map
    在涉及频繁添加和 删除密钥对

是的,我注意到了。当我将一个函数设置为一个值时@JonathanLonowski你能想到我什么时候应该这么做吗tho:(想到usec很难
const a = {};
a[document.body] = 'stackoverflow';

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