【问题标题】:Access JavaScript map similarly to plain object访问 JavaScript 映射类似于普通对象
【发布时间】:2017-07-02 23:22:08
【问题描述】:

我正在使用地图

因为我想存储一个对象作为键。

我的问题是 - 我可以像访问普通对象一样访问地图吗?

例如:

let m = new Map();
let obj = {foo:'bar'};
m[obj] = 'baz';
console.log(m[obj]);

这应该按原样正常工作,还是我需要使用 Map 的 get/set 方法?

我问的原因是,如果我需要使用 get/set,它会迫使我仔细重构大量代码。

这是一个可能需要重构的真实代码示例:

// 之前(broker.wsLock 是普通对象)

function addWsLockKey(broker, ws, key) {
  let v;
  if (!( v = broker.wsLock[ws])) {
    v = broker.wsLock[ws] = [];
  }
  if (v.indexOf(key) < 0) {
    v.push(key);
  }
}

//之后(broker.wsLock是一个Map实例)

function addWsLockKey(broker, ws, key) {
  let v;
  if (!( v = broker.wsLock.get(ws))) {
    v = [];
    broker.wsLock.set(ws, v);
  }
  if (v.indexOf(key) < 0) {
    v.push(key);
  }
}

有没有办法将 v 设置在与 set() 调用相同的行上?

【问题讨论】:

  • 一个 Map 就像任何其他 JS 对象一样,所以你可以像你正在做的那样添加属性,但是,你正在做的是添加一个属性 "[object Object]" - 而不是添加一个实际的地图条目。换句话说,你需要使用 set/get
  • 我刚刚在控制台中尝试了您的示例 - 它似乎工作正常。
  • @Zac,它只是看起来有效,该值实际上并未分配给由实际对象表示的属性,而是设置为 Jaromanda X 提到的名为 [object Object] 的属性。
  • 使用m.set(obj, 'baz'); console.log(m.get(obj));
  • 是的,我正在寻找一个明确的答案,使用括号表示法真的很方便,让我用一个更好的例子来更新这个问题。

标签: javascript node.js dictionary


【解决方案1】:

如果要访问Map 对象的实际值,则必须使用.get().set() 或各种迭代器。

var m = new Map();
m.set("test", "foo");
console.log(m.get("test"));    // "foo"

Map 上的常规属性访问,例如:

m["test"] = "foo"

只是在对象上设置一个常规属性 - 它不会影响实际的地图数据结构。

我想这样做是为了让您可以将Map 对象属性与Map 数据结构的成员分开访问,并且两者不应相互混淆。


此外,常规属性只接受字符串作为属性名称,因此您不能使用常规属性来索引对象。但是,地图对象在使用.set().get() 时具有这种能力。


您要求对此给出“确定的”答案。在ES6 specification 中,您可以查看.set() 的作用,并看到它在[[MapData]] 内部插槽上运行,这肯定与对象的属性不同。同样,该规范中没有任何地方说使用普通属性访问将访问内部对象[[MapData]]。所以,你只需要看到一个对象的普通属性访问是描述的。 MapObject 并且在 Map 规范中没有任何内容表明正常的属性访问应该与对任何其他对象的行为有所不同。事实上,它必须对Map 对象上的所有方法执行相同的操作,否则如果您碰巧在Map 中使用与方法名称相同的键放置项目,它们将不起作用。所以,你的证明是这样的:

  1. 一个简单的测试会告诉您,属性访问不会在 Map 本身中添加任何内容,而只是一个常规属性。
  2. 规范将Map 描述为一个对象。
  3. 规范描述了.get().set() 如何在内部插槽[[MapData]] 上运行。
  4. 规范中没有规定对Map 对象的属性访问应该与以往不同。
  5. 如果属性访问确实访问了MapData,那么如果您碰巧在Map 中放置了与方法名称冲突的键,那么您将无法访问方法 - 如果这是案例。

【讨论】:

  • 明白了,有道理
  • 是的,我需要使用 map 的原因是我可以使用对象作为键。感谢您的信息。
  • 但是,我正在寻找这种便利:
  • 让 v = obj[x] = obj[x] || '富';
  • @Olegzandr - 我还发现处理分配给地图的默认值很痛苦。我通常最终使用辅助函数或 map 的子类,它具有新版本的 .set() 为您处理默认值。就我而言,这是当我有一个数组映射时,我需要向现有数组添加一个项目或初始化一个新数组,但这是同一类型的问题。只需为自己创建一些辅助函数或 Map 的子类,并使用一些新方法来满足您的需求。
猜你喜欢
  • 2020-03-08
  • 2020-08-19
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 2012-04-03
  • 1970-01-01
  • 2014-07-04
相关资源
最近更新 更多