前記事の続き
結局、どちらも同じようなことができることはわかったので、パフォーマンス的にどちらを利用するかを検証してみます。
Perflikを利用して、各処理のブラウザでのパフォーマンスを図ってみた。
(macOS Monterey)
Chrome Version 99
Safari Version 15.4
Firefox Version 98
(windows 10)
Edge Version 99
m.set(x, y)
vs o[x] = y
いずれのブラウザでも、Objectの方が速い。
m.get(x)
vs o[x]
こちらもいずれのブラウザでもObjectの方がやや速い。
(このテストはランダム性があるので何回行ってみた)
m.delete(x)
vs delete o[x]
これは各ブラウザでばらつきがでた。Chrome,Edgeだと delete メソッドの方が速いが、Safariだとdeleteオペレータの方が速い。Firefoxはほぼ同じくらいだがmapの方がやや速い。
これはいくつかの操作のパターンを試してみた。
// 1. Map: for of パターン
for(const [k, v] of m){ sum += v; }
// 2. Map: forEachメソッドパターン
m.forEach((v, k) => { sum += v; });
// 3. Map: 配列に変換し、ArrayのforEachを使うパターン
[...m].forEach(([k, v]) => { sum +=v });
// 4. Map: 配列に変換し、for文を使うパターン
let sum = 0;
const _m = [...m];
const len = _m.length;
for(let i = 0;i < len; i++){ sum += _m[i][1]; }
// 5. Object: Object.entriesでfor..ofを使うパターン
for(const [k, v] of Object.entries(o)){ sum += v }
// 6. Object: Object.values で for..ofを使うパターン
for(const v of Object.values(o)){ sum += v }
// 7. Object: Object.keys で for..ofを使うパターン
for(const k of Object.keys(o)){ sum += k }
// 8. Object: Object.values で ArrayのforEachを使うパターン
Object.values(o).forEach((v) => sum += v )
// 9. Object: Object.values で for文を使うパターン
const vas = Object.values(o);
const len = vas.length;
for(let i = 0; i < len; i++){ sum += vas[i] }
// 10. Object: for..inのパターン
for(const k in o){ if(o.hasOwnProperty(k)){sum += o[k]} }
Object.values
で変換し、昔ながらのfor文を使って走査するのが速い。for(const v of Object.values(o))
forEach
がどのブラウザでも速かった。for..in
が次点で速かった。結論としては、走査の書き方によって処理速度が顕著に変わる、mapの場合は forEach
一択である。Objectの場合はvalue限定であれば、通常のfor文を利用するが一番速いが、バランスを取って for(const v of Object.values(o)){}
でもよいと思われる。
ObjectとMapは同じ使い方ができるが、Mapを使う場合の指標としては以下の点が上げられる
Object.keys
や Object.values
を使わずに走査できるので、可読性が上がり、処理速度も速い。size
メソッドによる恩恵も大きいと思うJavaScriptはもともと辞書型を定義するものがObjectしかなかったので、仕方なくそれを使っていた面もあるので、機会(と要件)が合うのであれば積極的にMapも使って行きたい所である。