将键组合到由基元和对象组成的 ES6 Map
Composing keys to ES6 Map made of both primitives and objects
ES6 Maps 可以使用具有任何值的键,包括函数、对象和任何原语。我想创建一个包含字符串和对 DOM-node.
的引用的组合键
var map = new Map();
var myKey = document.body + 'my string'
map.set(myKey, 'my value')
显然这行不通,上面的加法将计算为 [object HTMLBodyElement]my string
。我该怎么做?
你不能按照你字面上描述的那样去做,但你可以有地图中的地图。我可能会使用由相关字符串键入的 WeakMap
keyed by the DOM reference (so that it doesn't force the element to remain in memory if it's removed by DOM manipulation), where the value is a 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 中。
示例:
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>
使用此自定义 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))
ES6 Maps 可以使用具有任何值的键,包括函数、对象和任何原语。我想创建一个包含字符串和对 DOM-node.
的引用的组合键var map = new Map();
var myKey = document.body + 'my string'
map.set(myKey, 'my value')
显然这行不通,上面的加法将计算为 [object HTMLBodyElement]my string
。我该怎么做?
你不能按照你字面上描述的那样去做,但你可以有地图中的地图。我可能会使用由相关字符串键入的 WeakMap
keyed by the DOM reference (so that it doesn't force the element to remain in memory if it's removed by DOM manipulation), where the value is a 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 中。
示例:
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>
使用此自定义 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))