Javascript ES6 Map垫片是如何工作的

Javascript ES6 Map垫片是如何工作的,javascript,typescript,ecmascript-6,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 这是因为JavaScript对象{}键只能是字符串(至少在ES5中是这样) 但我看到Ma

根据我对文档(和)的理解,需要对内存地址进行引用才能正常工作:

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
这是因为JavaScript对象
{}
键只能是字符串(至少在ES5中是这样)

但我看到
Map
shim可用:。我试着阅读源代码,但它太过简洁抽象(使用)

问题: 请回答下列任何问题

  • 有没有一个简单的技巧,它真的可以做到(没有严格化)
  • 也许它会变异
    foo
    ,在其上存储一些字符串,然后将其用作键
  • 还有别的,也许我看错了文件

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

var myObj = {};

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

console.log(someArray.indexOf(myObj)); // returns 2
以下是另一个答案的实现:


我想到了两种方法。首先,显然,您可以拥有一个键数组,然后线性搜索它:

Map1={
密钥:[],
值:[],
};
Map1.set=函数(键,值){
var k=this.keys.indexOf(key);
if(k<0)
this.keys[k=this.keys.length]=key;
这个。值[k]=val;
};
Map1.get=函数(键){
返回this.values[this.keys.indexOf(key)];
};
foo={};
bar={};
Map1.set(foo,'xxx');
Map1.set(条,'yyy');

document.write(Map1.get(foo)+Map1.get(bar)+“
看看我的polyfill。我不是在宣传我的polyfill,而是说它是我迄今为止发现的最简单、最直接的,因此它最适合于学习和教育分析。基本上,它的工作原理是使用键的查找表和对应的值表,如下所示

var k = {}, j = [], m = document, z = NaN;
var m = new Map([
    [k, "foobar"], [j, -0xf], [m, true], [z, function(){}]
]);




Index      Key                 Value
##### ################    ################
0.    k ({})              "foobar"
1.    j ([])              -15
2.    m (Document)        true
3.    z (NaN)             function(){}
在内部,每个项目都存储在不同的索引中,或者至少我喜欢这样做。这也类似于浏览器内部实现它的方式。不幸的是,我看到其他一些多边形填充尝试将密钥存储在对象本身上,并干扰所有内部方法来隐藏它,导致整个网页运行速度慢10000%,而地图运行速度慢得几乎需要一毫秒才能设置和获取新属性。此外,我无法想象他们为了修补所有内部方法(如
hasOwnProperty
)而花费了多少时间


至于我的polyfill如何工作以及为什么工作,javascript对象存储在内存中的不同位置。这就是为什么
[]!==[]
和javascript对象数组上的indexOf正常工作。这是因为它们不是相同的数组。

我很确定垫片只是使用
==
来比较对象标识,因此有许多O(N)操作,而不是本机实现可能具有的O(1)或O(log(N))操作。ES2015
映射
无法正确填充,我相信最接近的实现方式是记录键、某种迭代以及与对象的定期比较,正如Jeremy提到的那样。易读的多边形填充btw@ArtoAle在接受的答案中,在用于查找解决方案的键上变异并添加一个
\u id
。然而,我的怀疑是正确的,ES5没有零影响的实现。感谢您花费的所有时间@basarat完全同意-您可以通过修改密钥对象来提高性能-即使您可能无法这样做,例如,如果
密钥
已通过
对象。冻结
var k = {}, j = [], m = document, z = NaN;
var m = new Map([
    [k, "foobar"], [j, -0xf], [m, true], [z, function(){}]
]);




Index      Key                 Value
##### ################    ################
0.    k ({})              "foobar"
1.    j ([])              -15
2.    m (Document)        true
3.    z (NaN)             function(){}