4

说我有:

const m = new Map();

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

for(let v of m){

}

对比

m.forEach(v => {});

我假设Map.protoype.forEach使用迭代器就像 for..of? 我在这里读到,在迭代期间使用 for..of 从地图中删除键是安全的,请参阅:ES6:在 Set/Map 迭代期间从 Set/Map 中删除元素是否危险?

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

4

2 回答 2

1

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

如下的 for-of 循​​环:

for (let entry of testMap) ...

与 forEach 相比,在迭代整个事物时,chrome 的性能始终快 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使用每次调用创建的匿名函数表达式调用时产生的潜在垃圾更少。

于 2019-01-23T11:32:12.007 回答
0

在 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
于 2018-07-18T05:52:26.620 回答