Using Array objects as key for ES6 Map

。_饼干妹妹 提交于 2019-12-10 01:52:16

问题


I am trying to update my code to ES6 as I am using Node 4.0 and really like its features so far. However I have problems with the new ES6 Map data structure as it behaves differently to {} when using Array as a key. I am using it as a counter map.

I run this code and I would like to know how I can use arrays as keys for the Map.

"use strict";

var a = new Map();
a.set(['x','y'], 1);
console.log(a.get(['x','y']));

var b = {};
b[['x','y']] = 1;

console.log(b[['x','y']]);

It prints out the following and the first line should be 1 and not undefined:

undefined
1

The original JS map stringifies the key and I am not wanting to do the same type of stringify hack with the new ES6 Map.

What can I do to use arrays as keys reliably for a ES6 Map?


回答1:


Understand that ES2015 Map keys are compared as if with the === operator. Two array instances, even if they contain the same values, do not ever compare as === to each other.

Try this:

var a = new Map(), key = ['x', 'y'];
a.set(key, 1);
console.log(a.get(key));

Since the Map class is intended to be usable as a base class, you could implement a subclass with an overriding .get() function, maybe.




回答2:


You need to save a reference to the non-primitive instance of Array you used as a key. Notice the difference in the following two examples:

"use strict";

var a = new Map();
a.set(['x','y'], 1);
console.log(a.get(['x','y']));
console.log(['x','y'] === ['x','y']);

var b = new Map();
var array = ['x','y'];
b.set(array, 1);
console.log(b.get(array));
console.log(array === array);



回答3:


I also had this need, so I wrote an ISC-licensed library: array-keyed-map. You can find it on npm. I think the source is quite clear, but here's how it works anyway, for posterity:


Maintain a tree of Map objects. Each tree stores:

  • Under an internally-declared Symbol key: The value at that point in the tree (if any). The Symbol guarantees uniqueness, so no user-provided value can overwrite this key.

  • On all its other keys: all other so-far set next-trees from this tree.

For example, on akmap.set(['a', 'b'], true), the internal tree structure would be like—

'a':
  [value]: undefined
  'b':
    [value]: true

Doing akmap.set(['a'], 'okay') after that would just change the value for the path at 'a':

'a':
  [value]: 'okay'
  'b':
    [value]: true

To get the value for an array, iterate through the array while reading the corresponding keys off the tree. Return undefined if the tree at any point is non-existent. Finally, read the internally declared [value] symbol off the tree you've gotten to.

To delete a value for an array, do the same but delete any values under the [value]-symbol-key, and delete any child trees after the recursive step if they ended up with a size of 0.


Why a tree? Because it's very efficient when multiple arrays have the same prefixes, which is pretty typical in real-world use, for working with e.g. file paths.



来源:https://stackoverflow.com/questions/32660188/using-array-objects-as-key-for-es6-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!