Syntax for creating objects with composite keys in JavaScript

Object property names in JavaScript are at the end just strings, your second example seems to work because the bracket property accessor converts the [1, 2] expression to String (returning "1,2"), for example:

var obj = {};
obj[[1, 2]] = 3;

console.log(obj["1,2"]); // 3

Another example:

var foo = { toString: function () { return "bar"; } },
    obj = {};

obj[foo] = 3; // foo is converted to String ("bar")
console.log(obj["bar"]); // 3

See also:

  • jshashtable

If you don't want to do string concatenation you can use nested maps, then a wrapper to make the code a less verbose. Here's an example in TypeScript.

class MapMap<Ka, Kb, V> implements Iterable<[Ka, Kb, V]> {
  readonly mm = new Map<Ka, Map<Kb, V>>()

  get(a: Ka, b: Kb): V | undefined {
    const m = this.mm.get(a)
    if (m !== undefined) {
      return m.get(b)
    }
    return undefined
  }

  set(a: Ka, b: Kb, v: V): void {
    let m = this.mm.get(a)
    if (m === undefined) {
      this.mm.set(a, (m = new Map()))
    }
    m.set(b, v)
  }

  *[Symbol.iterator](): Iterator<[Ka, Kb, V]> {
    for (const [a, m] of this.mm) {
      for (const [b, v] of m) {
        yield [a, b, v]
      }
    }
  }
}