1. 背景
mdn: Map是ES6中的内置全局对象,其中保存了多个键值对映射关系。
它的key 和value 都可以是js中的任意对象。例如,
const m = new Map;
const objectKey1 = {};
const objectKey2 = {};
const stringKey3 = '';
const numberKey4 = Infinity;
m.set(objectKey1, 1);
m.set(objectKey2, 2);
m.set(stringKey3, 3);
m.set(numberKey4, 4);
const iter = m.keys();
console.assert(iter.next().value === objectKey1);
console.assert(iter.next().value === objectKey2);
console.assert(iter.next().value === stringKey3);
console.assert(iter.next().value === numberKey4);
这里我们看到,m.keys()
是按key的插入顺序返回的。
mdn中的解释如下,
但是这种顺序性到底是否与实现相关呢,还是一种规范呢。
下面我们查阅ECMAScript规范来确认下。
2. Map
规范中Map相关的章节中,并没有提及顺序性。
只是对实现有这样的限制,
2.1 Map.prototype.keys
我们直接看Map.prototype.keys的操作语义,
其中,CreateMapIterator会返回一个iterator,
2.2 %MapIteratorPrototype%
%MapIteratorPrototype%是Map返回的所有iterator的原型对象。
我们来看它的next方法是怎样定义的,
其中第9步是关键,entries
是一个List,它的值是m.[[MapData]]
。
其中List是一个规范内置类型(Specification Types)。
因此,List是有顺序的。
2.3 [[MapData]]
那么m.[[MapData]]
是怎么来的呢?它是在Map的构造函数中初始化的。
第3步,构造函数初始化map.[[MapData]]
为一个空List。
2.4 Map.prototype.set
再看Map.prototype.set,
看第8步,可见Map中的key在逻辑上是顺序存储的。
参考
mdn: Map