1

ES6 Maps 使得使用任何值的键成为可能,包括函数、对象和任何原语。我想用一个字符串和一个对 DOM 节点的引用创建一个组合键。

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

map.set(myKey, 'my value')

显然这不起作用,上面的加法将评估为[object HTMLBodyElement]my string. 我该怎么做呢?

4

2 回答 2

2

你不能做你字面上描述的事情,但你可以有一张地图。我可能会使用WeakMapDOM 引用的键控(这样如果元素被 DOM 操作删除,它不会强制元素保留在内存中),其中值是Map由相关字符串键控的。例如:

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>

于 2018-06-29T14:21:01.297 回答
0

使用这个 custom MultiKeyMap,您可以创建一个映射,该映射基于您constructor在实例化时传递给的数字来接受任何数字键。但是,请注意,键的元组是有序的:

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))

于 2018-06-29T14:43:43.703 回答