直接迭代 Map 和通过 entries() 返回的迭代器迭代 Map 之间有区别吗?

Is there a difference between iterating a Map directly and via an iterator returned by entries()?

如果我在 JavaScript 中有一个 Map,例如

const myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')

那么这两个似乎都可以有效地遍历键值对 (以及我目前不感兴趣的许多其他选项):

// with .entries()
for (const [key, value] of myMap.entries()) {
  //
}
// without
for (const [key, value] of myMap) {
  //
}

有没有他们不这样做的极端情况?

Is there any edge case where they do not do the same?

没有。您从 entries 获得的迭代器对象与地图本身提供的完全相同。事实上,someMap[Symbol.iterator](当你向一个对象询问其迭代器时调用的函数)实际上与 someMap.entries:

完全相同的函数

const someMap = new Map();
console.log(someMap[Symbol.iterator] === someMap.entries);

在规范中:

默认情况下两者完全相同。

当使用 for...of is used with a value as for (const item of collection) then the well-known symbol @@iterator 查找值时。

对于 Map 个对象,@@iterator will return .entries()。这与调用方法完全一样,因为它 :

const map = new Map();

console.log(map[Symbol.iterator] === map.entries);

因此,两个循环将执行相同的操作。

小提示:即默认。如果 @@iterator 符号被覆盖,则可能有不同的结果:

const myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')

myMap[Symbol.iterator] = function* () {
  const entries = this.entries();
  for (const [key, value] of entries)
    yield [key, value.toUpperCase()]; //transform the value
}

// with .entries()
for (const [key, value] of myMap.entries()) {
  console.log("with .entries()", key, value)
}
// without
for (const [key, value] of myMap) {
  console.log("without", key, value)
}

然而,这种情况极少发生。如果它 确实 那么提供地图的人可能实际上 想要 不同的迭代逻辑。