ES6 Map如何工作

bas*_*rat 14 javascript typescript ecmascript-6

根据我对文档的理解(这里这里),需要引用内存地址才能工作:

const foo = {};
const map = new Map();
map.set(foo,'123');  // Can only be done if memory address of `foo` is known. Any other shimming would require stringification of foo
Run Code Online (Sandbox Code Playgroud)

这是因为JavaScript对象{}键只能是字符串(至少在ES5中).

但是我看到Map垫片可用:https://github.com/zloirock/core-js#map.我尝试阅读源代码,但它过于整齐抽象(内部使用强大的集合,然后再导入10个文件)

请回答以下任何一项

  • 是否有一个简单的技巧,甚至可以真正完成(没有字符串化)?
  • 也许它会变异foo以在其上存储一些字符串然后将其用作关键字?
  • 还有别的,也许我正在阅读文档错误?

geo*_*org 10

有两种方式可以想到.首先,显然,您可以拥有一组键,并线性搜索:

Map1 = {
    keys: [],
    values: [],
};

Map1.set = function(key, val) {
    var k = this.keys.indexOf(key);
    if(k < 0)
        this.keys[k = this.keys.length] = key;
    this.values[k] = val;
};

Map1.get = function(key) {
    return this.values[this.keys.indexOf(key)];
};


foo = {};
bar = {};

Map1.set(foo, 'xxx');
Map1.set(bar, 'yyy');

document.write(Map1.get(foo) + Map1.get(bar) + "<br>")
Run Code Online (Sandbox Code Playgroud)

第二个选项是向用作键的对象添加一个特殊的"键"标记:

Map2 = {
    uid: 0,
    values: {}
};

Map2.set = function(key, val) {
    key = typeof key === 'object'
        ? (key.__uid = key.__uid || ++this.uid)
        : String(key);
    this.values[key] = val;
};

Map2.get = function(key) {
    key = typeof key === 'object'
        ? key.__uid
        : String(key);
    return this.values[key];
};


foo = {};
bar = {};

Map2.set(foo, 'xxx');
Map2.set(bar, 'yyy');

document.write(Map2.get(foo) + Map2.get(bar) + "<br>")
Run Code Online (Sandbox Code Playgroud)

与第一个选项不同,第二个选项是O(1).通过使uid不可写/可枚举,可以更准确地完成它.此外,每个都Map应该有自己的"uid"名称(这可以在Map构造函数中轻松设置).


Pet*_*ter 8

诀窍是存储在一个数组中并通过迭代和使用严格比较在O(n)时间内执行查找 - 而不是使用真正的哈希函数,这将是O(1)查找.例如,考虑一下:

var myObj = {};

var someArray = [{}, {}, myObj, {}];

console.log(someArray.indexOf(myObj)); // returns 2
Run Code Online (Sandbox Code Playgroud)

这是我从另一个答案的实现:Javascript HashTable使用Object键

function Map() {
    var keys = [], values = [];

    return {
        put: function (key, value) {
            var index = keys.indexOf(key);
            if(index == -1) {
                keys.push(key);
                values.push(value);
            }
            else {
                values[index] = value;
            }
        },
        get: function (key) {
            return values[keys.indexOf(key)];
        }
    };
}
Run Code Online (Sandbox Code Playgroud)