组成由基本体和对象组成的ES6 Map的键

时间:2018-06-29 14:11:22

标签: javascript es6-map

ES6 Maps使得可以使用具有任何值的键,包括函数,对象和任何基元。我想创建一个包含字符串和对DOM节点的引用的组合键。

var map = new Map();
var myKey = document.body + 'my string'

map.set(myKey, 'my value')

显然这是行不通的,上面的加法运算结果为[object HTMLBodyElement]my string。我将如何去做?

2 个答案:

答案 0 :(得分:2)

您无法执行您所说的话,但是您可以拥有一张地图。我可能会使用以DOM引用作为键的WeakMap(这样,如果通过DOM操作将其删除,它就不会强制该元素保留在内存中),其中值是一个由{相关的字符串。例如:

let entriesByElement = new WeakMap();

设置元素:

let map = entriesByElement.get(document.body);
if (!map) {
    map = new Map();
    entriesByElement.set(document.body, map);
}
map.set(keyString, value);

获取元素:

let map = entriesByElement.get(document.body);
let value = map && map.get(keyString);

(该示例假定您不会将undefined作为有效的存储值。)

您可以将其包装在一个类中。

示例:

class ExampleStore {
    constructor() {
        this.entriesByElement = new WeakMap();
    }
    set(element, string, value) {
        let map = this.entriesByElement.get(element);
        if (!map) {
            map = new Map();
            this.entriesByElement.set(element, map);
        }
        map.set(string, value);
    }
    get(element, string) {
        const map = this.entriesByElement.get(element);
        return map && map.get(string);
    }
}

const store = new ExampleStore();

let div1 = document.getElementById("one");
let div2 = document.getElementById("two");

store.set(div1, "a", "ayy");
store.set(div1, "b", "bee");

store.set(div2, "a", "alpha");

console.log(store.get(div1, "a")); // "ayy"
console.log(store.get(div1, "b")); // "bee"

console.log(store.get(div2, "a")); // "alpha"
console.log(store.get(div2, "b")); // undefined (doesn't have that entry)

// Removing div1
document.body.removeChild(div1);
div1 = null;

console.log(store.get(div1, "a")); // May be undefined, if the element has been
                                   // cleaned up (it is for me on Chrome,
                                   // Firefox and Edge), since we're using a
                                   // WeakMap.
<div id="one"></div>
<div id="two"></div>

答案 1 :(得分:0)

使用此自定义MultiKeyMap,您可以创建一个映射,该映射根据实例化时传递给constructor的数字来接受任何数字键。但是,请注意,键的元组是 ordered

class MultiKeyMap extends Map {
  constructor (keys = 1) {
    if (keys < 1) {
      throw new RangeError('keys must be greater than 0')
    }

    // 1 key is just a normal Map
    if (keys === 1) {
      return new Map()
    }

    super()
    this.keys = keys
  }
  
  get (key, ...keys) {
    if (arguments.length !== this.keys) {
      throw new RangeError('Unexpected number of keys')
    }

    // return early
    if (!super.has(key)) {
      return undefined
    }

    return super.get(key).get(...keys)
  }

  // (...keys, value) is an illegal signature
  set (key, ...args) {
    if (args.length !== this.keys) {
      throw new RangeError('Unexpected number of keys')
    }

    if (!super.has(key)) {
      super.set(key, new MultiKeyMap(this.keys - 1))
    }

    return super.get(key).set(...args)
  }
  
  has (key, ...keys) {
    if (arguments.length !== this.keys) {
      throw new RangeError('Unexpected number of keys')
    }

    return super.has(key) && super.get(key).has(...keys)
  }
}

const map = new MultiKeyMap(2)

map.set(document.body, 'my string', 'my value')

console.log(`document.body, 'my string'`)
console.log(map.has(document.body, 'my string'))
console.log(map.get(document.body, 'my string'))
console.log(`'my string', document.body`)
console.log(map.has('my string', document.body))
console.log(map.get('my string', document.body))