带有复合键的 Javascript 映射

And*_*elt 5 javascript dictionary

在 JavaScript 中,我想将值存储到复合键,类似于以元组为键的 C# 字典。这是我遇到 Map 类的地方。但是,它似乎并没有我希望的那么好。这是我目前的方法:

var test = new Map();

test.set({a: 1, b: 1}, 'Bla');
test.set({a: 5, b: 7}, 'Blub');

test.get({a: 1, b: 1}); // ==> Returns undefined; would expect 'Bla'
Run Code Online (Sandbox Code Playgroud)

我想,这与{a: 1, b: 1}具有不同内存地址的两个对象有关,因此相同但不相同。Dictionaryc# 中的类在后台使用哈希函数。JS中有类似的东西吗?或者更简单的方法?

我真正的关键对象由三个字符串组成。

Max*_*Max 6

你的分析是正确的。它的工作原理是这样的,因为在 Javascript 中,您通常操作原始对象,这些对象没有开箱即用的附加所有这些哈希行为。不过,没有什么可以阻止您在后台使用哈希函数实现自己的字典

class Dictionary {
  map = {}

  constructor(hashFunction) {
    this.hashFunction = hashFunction
  }

  set(key, item) {
    this.map[this.hashFunction(key)] = item
  }

  get(key) {
    return this.map[this.hashFunction(key)]
  }

  delete(key) {
    delete this.map[this.hashFunction(key)]
  }
}

const dict = new Dictionary((keyObject) => JSON.stringify(keyObject))
dict.set({ a: 1, b: 2 }, 'hello')
console.log(dict.get({ a: 1, b: 2 })) // hello
Run Code Online (Sandbox Code Playgroud)

至于使用什么,Map还是object,Map和object之间的区别很简单,object只支持字符串键(也是Symbols,但现在不相关),而Map支持任何值,但代价是使用更多资源,与旧浏览器的兼容性较差,而且它通常不如 object 使用方便(并且还会阻止 GC 清除那些用作键的对象)。也就是说,对象是你的选择


Mhm*_*z_A 5

{}该运算符每次都会创建一个新对象;并且新对象每次都会有不同的对象引用;如果您保存对象引用并将其用于多个操作,那就可以了;但因为你每次都尝试使用新的对象引用,这是行不通的;您可以使用原始类型作为键,也可以使用相同的对象引用,如下面的代码片段

//approach 1 using same object reference
var test = new Map();
var obj = {a: 1, b: 1};
test.set(obj, 'Bla');
test.set({a: 5, b: 7}, 'Blub');
let result = test.get(obj); 
console.log(result);

// aproach 2 using JSON.stringify
test = new Map();
test.set(JSON.stringify({a: 1, b: 1}), 'Bla');
test.set({a: 5, b: 7}, 'Blub');
result = test.get(JSON.stringify({a: 1, b: 1})); 
console.log(result)
Run Code Online (Sandbox Code Playgroud)

  • @AndréReichelt 是的,当然,您甚至可以考虑 `JSON.stringify()` 该对象使用对象字符串作为键;即使两个对象具有不同的引用,但结构相同;json.stringify 结果是相同的 (2认同)