更高的性能 - Map.prototype.forEach 或 for..of?

Higher perf - Map.prototype.forEach or for..of?

假设我有:

const m = new Map();

两者之间是否存在性能差异:

for(let v of m){

}

对比

m.forEach(v => {});

我假设 Map.protoype.forEach 像 for..of 一样使用迭代器?我在这里读到在迭代期间使用 for..of 从地图中删除键是安全的,请参阅:

我想知道使用 Map.prototype.forEach 循环从地图中删除键是否安全。

在 node.js 8.11

上使用以下代码做了一些基准测试
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();

suite
  .add('for of', function () {
    const m = new Map();
    for (let i = 0; i < 100; i++) {
      m.set(`key${i}`, i);
    }

    for (let v of m) {
      m.delete(v);
    }
  })
  .add('forEach', function () {
    const m = new Map();
    for (let i = 0; i < 100; i++) {
      m.set(`key${i}`, i);
    }

    m.forEach(v => {
      m.delete(v);
    })
  })
  .on('cycle', function (event) {
    console.log(String(event.target));
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  })
  // run async
  .run({ 'async': true });

结果很有趣:

for of x 88,105 ops/sec ±0.36% (89 runs sampled)
forEach x 81,532 ops/sec ±0.55% (90 runs sampled)
Fastest is for of

我也对此很感兴趣,并创建了一个 JSPerf benchmark,它对地图执行简单的原始迭代,但不对条目本身做任何事情。

像下面这样的 for-of 循​​环:

for (let entry of testMap) ...

在 chrome 中,与 forEach 相比, 在遍历整个事物时始终比 forEach 快 15-20%。

如果你需要更好的可读性,循环表达式本身的数组解构是最慢的,它实际上在forEach的级别上执行:

for (let [key, value] of testMap) ...

使用局部变量介于两者之间,比数组解构快但比原始循环慢:

for (let entry of testMap) {
    let key = entry[0];
    let value = entry[1];
}

此外,for-of 循​​环还具有不需要创建函数的额外好处,这意味着在使用每次调用创建的匿名函数表达式调用 forEach 时产生的潜在垃圾更少。